当我似乎明白了什么是回报在Haskell,我试着用不同的选择玩,似乎回报不仅可以随时随地在单子链中使用,也可以完全排除
*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
即使我省略我自己的实例化回报,我只得到警告...
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'
我仍然可以使用单子
*Main> JustG 9 >>= \y -> (JustG 11) >>= \x -> (JustG y)
JustG 9
*Main> JustG 9 >>= \y -> (NothingG) >>= \x -> (JustG y)
NothingG
那么什么特别之处return关键字? 这是关于更复杂的情况下,我不能忽略它? 或者是因为这是“正确”的方式做事情,即使他们可以做不同?
UPDATE:..或另一种选择,我可以定义自己的一元价值构造
finallyMyLastStepG :: Int -> MaybeG Int
finallyMyLastStepG a = JustG a
并产生相同链的另一变型(具有相同的结果)
*Main> JustG 9 >>= \y -> (JustG 11) >>= \x -> (finallyMyLastStepG y)
JustG 9
那么什么特别之处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
所以,你看到return
是,给定类型的值的函数a
返回类型的新值ma
,其中m
是某种类型就是实例Monad
。 这些类型包括:
- 单子
[]
- 单子
I0
- 单子
Maybe
- 单子
STM
- 单子
((->) r)
- 单子
(Either e)
- 单子
(ST s)
等等再说。 “单子”的情况下,应满足下列法律:
> return a >>= k == k a
> m >>= return == m
> m >>= (\x -> k x >>= h) == (m >>= k) >>= h
函数的实现a -> ma
是很容易猜到。 下面是最常见的单子的定义:
列表 :
return x = [x]
也许
return x = Just x
所以,你看到return
是一个重载函数,“升降机”的值划分为一元的包装。 因此,你可以用它随时随地可以使用它的定义。 例如
Prelude> 1 : return 2
[1,2]
或者在do
概念 (有用的,当链接表达式 )。
> do v <- return 7 ; return v :: Maybe Int
Just 7
使用一个单子的真正原因return
是在一些单子组成多个值时:
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
在最后的陈述,你怎么看链条短路,一旦命中给定的单子零值。 在这种情况下Nothing
。
总结: return
是一个重载函数,升降机的值成一个monadic包装。 您可以使用它时,你需要解除值。 它不是一个控制流的关键字,因为它是在命令式语言。
我怀疑你是误会在哈斯克尔单子的背景是什么“回归”的意思。 返回的是一个函数 ,它在a
并返回一个“包装a
” -也就是说,最简单的单子可能的实例。 在其他语言中它通常被称为Unit
。 这不是“控制流” return
您在类似C语言中看到。
因此,在你的的一个例子Maybe
单子,我们的回报定义为发生在一个函数a
并返回一个Maybe a
:
return :: a -> Maybe a
而且它有什么作用? 如果你给它x
,它给你回Just x
:
return x = Just x
现在你可以使用return
当你需要的功能,而不是写出来的速记:
\x -> Just x
这就是所谓的return
,因为当你在写出单子do
记号,它看起来像你的类C语言做什么。
迈克·哈特尔评论使我对正确的方向,虽然不是那么正式恕我直言,所以我只是发表我的最后的理解有什么特别之处“回归”操作。
任何类型的类列表操作者它支持和有功能,可以在这个类上下文只工作(通过类constratint符号=>强加)。 因此,例如filterM签名
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
告诉我们,它只能在一元上下文中使用。 神奇的是,在身体这个功能可以自由使用任何运营商类有(>> =和返回Monad的),如果一个实例(例如我MaybeG)缺乏的方法(回在我的情况),这时可把功能失败。 因此,当回报是有
> filterM (\x -> JustG (x > 0)) [2, 1, 0, -1]
JustG [2,1]
当它的评论(见我的问题,实现MaybeG的)
> filterM (\x -> JustG (x > 0)) [2, 1, 0, -1]
*** Exception: Monad.hs:3:10-21: No instance nor default method for class operation GHC.Base.return
因此,任何运营商(在回报单子的情况下)的imlementation是必需的,如果一个公司计划用这个类(单子在这种情况下)约束的工作函数使用实例。
我想我的最初的误解是由于这样的事实,大多数的教程说明没有多态(临时)背景下单子链。 这方面在我看来,让单子更强大的和可重复使用。