Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 什么';It’关于',它很特别;返回';关键词_Haskell_Functional Programming_Monads - Fatal编程技术网

Haskell 什么';It’关于',它很特别;返回';关键词

Haskell 什么';It’关于',它很特别;返回';关键词,haskell,functional-programming,monads,Haskell,Functional Programming,Monads,当我似乎理解了哈斯克尔的回报是什么时,我尝试了不同的选择,似乎回报不仅可以在单子链的任何地方使用,而且可以完全排除 *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 >>= \

当我似乎理解了哈斯克尔的回报是什么时,我尝试了不同的选择,似乎回报不仅可以在单子链的任何地方使用,而且可以完全排除

*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 
即使我在自己的实例中忽略了return,我也只会得到警告

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关键字有什么特别之处呢?这是否涉及更复杂的情况,我不能忽略?还是因为这是一种“正确”的做事方式,即使可以用不同的方式来做

更新: .. 或者另一种选择,我可以定义自己的一元值构造函数

finallyMyLastStepG :: Int -> MaybeG Int
finallyMyLastStepG a = JustG a  
并产生相同链的另一个变体(具有相同的结果)


我怀疑你误解了“返回”在哈斯克尔的单子中的含义。return是一个函数,它接受一个
a
,并返回一个“wrapped
a
”——也就是说,monad的最简单实例。在其他语言中,它通常被称为
单元
。它不是在类似C语言中看到的“控制流”
return

因此,在您的
Maybe
单子示例中,我们将return定义为接受
a
并返回
Maybe a
的函数:

return :: a -> Maybe a
它有什么作用?如果你给它x,它只给你x:

return x = Just x
现在,您可以在需要该函数时使用
return
作为速记,而不是写出:

\x -> Just x
它被称为
return
,因为当你在
do
符号中写出单子时,它看起来就像你在C语言中所做的那样

那么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
的一个实例。这些类型包括:

  • 单子
    []
  • Monad
    I0
  • 单子
    可能
  • 单子
    STM
  • 单子
    ((->)r)
  • 单子
    (或e)
  • 单子
    (ST s)
除此之外还有很多。“Monad”的实例应符合以下法律:

> return a >>= k  ==  k a
> m >>= return  ==  m
> m >>= (\x -> k x >>= h)  ==  (m >>= k) >>= h
函数
a->ma
的实现非常容易猜测。以下是最常见单子的定义:

清单:

也许吧

因此,您可以看到
return
是一个重载函数,它将值“提升”到一元包装器中。因此,您可以在任何可以使用其定义的地方使用它。例如

Prelude> 1 : return 2
[1,2]
或者在(有用的时候)

在上一条语句中,您可以看到当给定单子的值为零时,链是如何短路的。在这种情况下,
无任何内容


摘要:
return
是一个重载函数,它将值提升到一元包装器中。当需要提升值时,可以使用它。它不是命令式语言中的控制流关键字。

Mike Hartl comment将我引向了正确的方向,尽管不是那么正式的imho,所以我只是发布了我对“return”运算符的最终理解

任何类型类都列出它支持的运算符,并且有一些函数只能在此类上下文中工作(通过类constratint symbol=>)。例如,filterM签名

filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] 
这说明它只能在一元上下文中使用。神奇的是,在函数体中,该函数可以自由使用该类拥有的任何运算符(>>=并返回Monad),如果一个实例(例如我的mayberg)缺少一个方法(在我的情况下返回),那么该函数可能会失败。所以,当回报在那里

> filterM (\x -> JustG (x > 0)) [2, 1, 0, -1] 
JustG [2,1]
当它被评论时(参见问题中我对Maybege的实现)

因此,如果计划将实例与处理此类(本例中为monad)约束的函数一起使用,则需要实现任何运算符(在monad情况下为return)


我认为我最初的误解是因为大多数教程解释一元链时没有多态(特别)上下文。在我看来,这种环境使monad更强大,更可重用

return
不是关键字。是的,它不像大多数命令式编程语言中同名的关键字那样控制流,所以
do{foo;return…;quox}
中的
return…
是多余的。@delnan,问题是当我读到关于monad的所有内容时,最后一行的“return”看起来像是需求。但在我的第三行中,我将其替换为直接一元值创建,Haskell对此没有问题。@Maksee:在最后一行有一个返回不是一个要求。恰好对于Maybe monad,bind操作包含一个新的简单monad的构造。通常情况并非如此;比如说,身份一元。它不调用
bind
中的任何内容
return
。好的,\x->(仅x)在我的第三行中的作用完全相同,它返回一元值它被称为
Unit
?AFAIK
Unit
作为空元组的替代名称(或者更抽象/一般/正确地说,只有一个值的类型)。@Maksee:
return
是monad模式的要求。我现在正在我的博客上为面向对象的程序员运行一系列关于monads的介绍;关于它,我说的是
CreateSimpleM
,而不是
return
,以保持清晰。你可能想看看,从底部开始。
return
不是语法。这是一个函数。尽管是多态的。从技术上讲,
Just
本身也是
(\x->Just x)
的合适替代品,因为
Just
是一个普通函数。。另外,看到埃里克·利珀特回答哈斯克尔的问题也很棒。
Prelude> 1 : return 2
[1,2]
> do v <- return 7 ; return v :: Maybe Int
Just 7
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
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] 
> filterM (\x -> JustG (x > 0)) [2, 1, 0, -1] 
JustG [2,1]
> 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