我刚开始玩Haskell(刚刚学习了绑定功能)。我喜欢它允许在Monad中从左到右链接后续操作的方式。
我想知道是否有办法更好地编写下面的代码?
main = do
print $ Just 10
>>= (\x -> return (x*2))
>>= (\x -> return (x*3))
感觉lambda和return可以用某种部分应用的函数代替。我在想这样的事情:
(###) :: Maybe Int -> (Int -> Int) -> Maybe Int
(Just x) ### f = Just (f x)
Nothing ### f = Nothing
main = do
print $ Just 10
>>= (\x -> return (x*2))
>>= (\x -> return (x*3))
### (+3) -- the result should be (Just 63)
当然这是丑陋的,非通用的,不会编译:):
monads.hs:8:13:
Couldn't match expected type `a0 -> Maybe b0'
with actual type `Maybe Int'
In the second argument of `(>>=)', namely
`(\ x -> return (x * 3)) ### (+ 3)'
In the second argument of `($)', namely
`Just 10 >>= (\ x -> return (x * 2))
>>= (\ x -> return (x * 3)) ### (+ 3)'
In a stmt of a 'do' block:
print
$ Just 10 >>= (\ x -> return (x * 2))
>>= (\ x -> return (x * 3)) ### (+ 3)
monads.hs:8:14:
Couldn't match expected type `a1 -> m0 a1'
with actual type `Maybe Int'
The lambda expression `\ x -> return (x * 3)' has one argument,
but its type `Maybe Int' has none
In the first argument of `(###)', namely `(\ x -> return (x * 3))'
In the second argument of `(>>=)', namely
`(\ x -> return (x * 3)) ### (+ 3)'
无论如何,它似乎是一个有用的工具,能够在monad中链接一系列操作而不必过多担心中间结果(没有do-notation)并且没有明确地指示代码何时回退到Nothing。
###
函数更改为通用,花花公子和编译?答案 0 :(得分:4)
恭喜,您刚刚发明了Functor
!查看Functor
Maybe
实例的source instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
:
m >>= return . f = fmap f m
这是一个较少提到的monad法则fmap
- monad行为和functor行为之间的一种“连贯性”法律。
(<$>)
还有一个中缀别名main = print ((+3) <$> (*2) <$> (*3) <$> Just 10)
,所以你可以写
Just 63
并输出<pre>
。