Mak*_*see 12 monads haskell functional-programming
当我似乎理解Haskell的回归时,我尝试使用不同的替代方案,似乎返回不仅可以在monad链中的任何地方使用,而且可以完全排除
*Main> Just 9 >>= \y -> (Just y) >>= \x -> return x
Just 9
*Main> Just 9 >>= \y -> (return y) >>= \x -> (Just y)
Just 9
*Main> Just 9 >>= \y -> (Just y) >>= \x -> (Just x)
Just 9
Run Code Online (Sandbox Code Playgroud)
即使我在自己的实例中省略了返回,我也只会收到警告......
data MaybeG a = NothingG | JustG a deriving Show
instance Monad MaybeG where
-- return x = JustG x
NothingG >>= f = NothingG
JustG x >>= f = f x
fail _ = NothingG
Monad.hs:3:10:
Warning: No explicit method nor default method for `return'
In the instance declaration for `Monad MaybeG'
Run Code Online (Sandbox Code Playgroud)
我仍然可以使用monad
*Main> JustG 9 >>= \y -> (JustG 11) >>= \x -> (JustG y)
JustG 9
*Main> JustG 9 >>= \y -> (NothingG) >>= \x -> (JustG y)
NothingG
Run Code Online (Sandbox Code Playgroud)
那么return关键字有什么特别之处呢?这是关于更复杂的情况,我不能省略它吗?或者因为这是做事的"正确"方式,即使它们可以以不同的方式完成?
更新: ..或另一种选择,我可以定义自己的monadic值构造函数
finallyMyLastStepG :: Int -> MaybeG Int
finallyMyLastStepG a = JustG a
Run Code Online (Sandbox Code Playgroud)
并生成同一链的另一个变体(具有相同的结果)
*Main> JustG 9 >>= \y -> (JustG 11) >>= \x -> (finallyMyLastStepG y)
JustG 9
Run Code Online (Sandbox Code Playgroud)
Don*_*art 37
那么return关键字有什么特别之处呢?
首先,return它不是 Haskell中的关键字.这是一个重载的功能.
其类型由下式给出:
class Monad m where
-- | Sequentially compose two actions, passing any value produced
-- by the first as an argument to the second.
(>>=) :: m a -> (a -> m b) -> m b
-- | Inject a value into the monadic type.
return :: a -> m a
Run Code Online (Sandbox Code Playgroud)
所以你看到这return是一个赋值类型的函数a,返回一个新的类型值m a,其中m某个类型是一个实例Monad.这些类型包括:
[]I0MaybeSTM((->) r)(Either e)(ST s)还有更多."Monad"实例应符合以下法律:
> return a >>= k == k a
> m >>= return == m
> m >>= (\x -> k x >>= h) == (m >>= k) >>= h
Run Code Online (Sandbox Code Playgroud)
函数的实现a -> m a很容易猜到.这是最常见的monad的定义:
列表:
return x = [x]
Run Code Online (Sandbox Code Playgroud)
也许
return x = Just x
Run Code Online (Sandbox Code Playgroud)
所以你看到这return是一个重载函数,它将一个值"提升"为一个monadic包装器.因此,您可以在任何可以使用其定义的地方使用它.例如
Prelude> 1 : return 2
[1,2]
Run Code Online (Sandbox Code Playgroud)
> do v <- return 7 ; return v :: Maybe Int
Just 7
Run Code Online (Sandbox Code Playgroud)
使用monadic的真正原因return是在一些monad中组合多个值:
Prelude> do x <- return 1 ; y <- return 2 ; return (x + y) :: Maybe Int
Just 3
Prelude> do x <- Nothing ; y <- return 2 ; return y
Nothing
Run Code Online (Sandbox Code Playgroud)
在最后一个语句中,您会看到链条在给定monad达到零值后如何短路.在这种情况下Nothing.
简介:return是一个重载函数,它将值提升为monadic包装器.您需要提升值时使用它.它不是一个控制流关键字,因为它是命令式语言.
Eri*_*ert 13
我怀疑你误解了"回归"在Haskell中的monad语境中意味着什么.return是一个函数,它接受一个a并返回一个"包装a" - 也就是monad最简单的实例.在其他语言中,它通常被称为Unit.这不是return你在C语言中看到的"控制流" .
所以在你的Maybemonad 示例中,我们将return定义为一个函数,它接受一个a并返回一个Maybe a:
return :: a -> Maybe a
Run Code Online (Sandbox Code Playgroud)
它做了什么?如果你给它x,它会让你回来Just x:
return x = Just x
Run Code Online (Sandbox Code Playgroud)
现在,您可以return在需要该功能时使用速记,而不是写出来:
\x -> Just x
Run Code Online (Sandbox Code Playgroud)
这是return因为当你用do符号写出monad时,它看起来就像你用C语言做的那样.