有什么特别之处“回报”关键字(What's so special about 're

2019-07-21 06:31发布

当我似乎明白了什么是回报在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

Answer 1:

那么什么特别之处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包装。 您可以使用它时,你需要解除值。 它不是一个控制流的关键字,因为它是在命令式语言。



Answer 2:

我怀疑你是误会在哈斯克尔单子的背景是什么“回归”的意思。 返回的是一个函数 ,它在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语言做什么。



Answer 3:

迈克·哈特尔评论使我对正确的方向,虽然不是那么正式恕我直言,所以我只是发表我的最后的理解有什么特别之处“回归”操作。

任何类型的类列表操作者它支持和有功能,可以在这个类上下文只工作(通过类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是必需的,如果一个公司计划用这个类(单子在这种情况下)约束的工作函数使用实例。

我想我的最初的误解是由于这样的事实,大多数的教程说明没有多态(临时)背景下单子链。 这方面在我看来,让单子更强大的和可重复使用。



文章来源: What's so special about 'return' keyword