haskell

时间:2016-02-11 10:32:58

标签: haskell

据我所知,代码

l = [(a,b)|a<-[1,2],b<-[3,4]]

相当于

l = do
  a <- [1,2]
  b <- [3,4]
  return (a,b)

[1,2] >>= (\a -> [3,4] >>= (\b -> return (a,b)))

此类表达式的类型为[(t,t1)],其中t和t1为Num。

如果我写的话

getLine >>= (\a -> getLine >>= (\b -> return (a,b)))

解释器读取两行并返回包含它们的元组。

但是我可以在列表生成器中使用getLine或类似的东西吗?

表达式

[x|x<-getLine]

返回错误“无法匹配预期类型[t0]' with actual type IO String'”

但是,当然,这可以使用do-notation或使用(&gt;&gt; =)。

列表生成器的重点是什么,它们与do-notation之间的实际区别是什么?

使用列表gens时是否有任何类型限制?

2 个答案:

答案 0 :(得分:9)

这是一个明智的观察,你不是第一个偶然发现的人。你是对的,[x|x<-getLine]的翻译会导致一个完全有效的monadic表达。关键是我认为列表推导只是作为列表的便捷语法引入的first,并且(可能)没有人认为人们可能会将它们用于其他monad。

但是,由于对[]的限制并非真正必要,因此有一个名为-XMonadComprehensions的GHC扩展名可以删除限制并允许您准确写出您想要的内容:

Prelude> :set -XMonadComprehensions 
Prelude> [x|x<-getLine]
sdf
"sdf"

答案 1 :(得分:6)

我的理解是列表推导只能 用于构建列表

然而,有一个名为“monad comprehensions”的语言扩展,允许你使用任意monad。

https://ghc.haskell.org/trac/ghc/wiki/MonadComprehensions