简体   繁体   English

带有monad的Haskell中表达式的结果

[英]Result of expressions in Haskell with monads

I'm currently preparing for my final exam regarding Haskell, and I am going over the Monads and we were giving an example such as: 我目前正准备参加关于Haskell的期末考试,我正在修改Monads,我们举了一个例子:

Given the following definition for the List Monad: 给出List Monad的以下定义:

instance Monad [] where
  m >>= f = concatMap f m
  return x = [x] 

where the types of (>>=) and concatMap are 其中(>>=)concatMap类型

 (>>=) :: [a] -> (a -> [b]) -> [b]
 concatMap :: (a -> [b]) -> [a] -> [b]

What is the result of the expression? 表达的结果是什么?

> [1,2,3] >>= \x -> [x..3] >>= \y -> return x
  [1, 1, 1, 2, 2, 3] //Answer

Here the answer is different from what I thought it to be, now we briefly went over Monads, but from what I understand (>>=) is called bind and could be read in the expression above as "applyMaybe". 这里的答案与我的想法不同,现在我们简单地介绍了Monads,但是根据我的理解(>>=)称为bind,可以在上面的表达式中读作“applyMaybe”。 In this case for the first part of bind we get [1,2,3,2,3,3] and we continue to the second part of the bind, but return x is defined to return the list of x. 在这种情况下,对于bind的第一部分,我们得到[1,2,3,2,3,3] ,我们继续到bind的第二部分,但return x被定义为返回x的列表。 Which should have been [1,2,3,2,3,3] . 应该是[1,2,3,2,3,3] However, I might have misunderstood the expression. 但是,我可能误解了这个表达方式。 Can anyone explain the wrong doing of my approach and how should I have tackled this. 任何人都可以解释我的方法的错误做法,我应该如何解决这个问题。 Thanks. 谢谢。

this case for the first part of bind we get [1,2,3,2,3,3] 这个案例对于绑定的第一部分我们得到[1,2,3,2,3,3]

Correct. 正确。

and we continue to the second part of the bind, but "return x" is defined to return the list of x. 并且我们继续绑定的第二部分,但是“return x”被定义为返回x的列表。 Which should have been [1,2,3,2,3,3]. 应该是[1,2,3,2,3,3]。

Note that, in... 请注意,在......

[1,2,3] >>= \x -> [x..3] >>= \y -> return x

... x is bound by (the lambda of) the first (>>=) , and not by the second one. ... x由第一个(>>=)的(lambda)绑定,而不是由第二个绑定。 Some extra parentheses might make that clearer: 一些额外的括号可能会更清楚:

[1,2,3] >>= (\x -> [x..3] >>= (\y -> return x))

In \\y -> return x , the values bound to y (that is, the elements of [1,2,3,2,3,3] ) are ignored, and replaced by the corresponding values bound to x (that is, the elements of the original list from which each y was generated). \\y -> return x ,绑定到y的值(即[1,2,3,2,3,3]的元素)将被忽略,并被绑定到x的相应值替换(即,生成每个y的原始列表的元素)。 Schematically, we have: 原理上,我们有:

[1,     2,   3] -- [1,2,3]
[1,2,3, 2,3, 3] -- [1,2,3] >>= \x -> [x..3]
[1,1,1, 2,2, 3] -- [1,2,3] >>= \x -> [x..3] >>= \y -> return x

First, let's be clear how this expression is parsed: lambdas are syntactic heralds , ie they grab as much as they can to their right, using it as the function result. 首先,让我们清楚这个表达式是如何解析的:lambdas是语法先驱 ,即它们尽可能多地抓取它们,使用它作为函数结果。 So what you have there is parsed as 所以你在那里被解析为

[1,2,3] >>= (\x -> ([x..3] >>= \y -> return x))

The inner expression is actually written more complicated than it should be. 内部表达式实际上写得比它应该更复杂。 y isn't used at all, and a >>= \\_ -> p can just be written as a >> p . y根本不使用, a >>= \\_ -> p可以写成a >> p There's an even better replacement though: generally, the monadic bind a >>= \\q -> return (fq) is equivalent to fmap fa , so your expression should really be written 虽然有一个更好的替代品:通常,monadic绑定a >>= \\q -> return (fq)相当于fmap fa ,所以你的表达式应该真的写

[1,2,3] >>= (\x -> (fmap (const x) [x..3]))

or 要么

[1,2,3] >>= \x -> map (const x) [x..3]

or 要么

[1,2,3] >>= \x -> replicate (3-x+1) x

At this point it should be pretty clear what the result will be, since >>= in the list monad simply maps over each element and concatenates the results. 此时应该非常清楚结果是什么,因为>>=在列表中monad只是映射每个元素并连接结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM