绑定函数替代而不显式返回Monad

时间:2017-07-09 22:33:56

标签: haskell

我刚开始玩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。

  1. 是否有内置功能?
  2. 如果没有,我应该如何将###函数更改为通用,花花公子和编译?

1 个答案:

答案 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>