我是哈斯凯尔的新手,我正在努力学习哈斯克尔 . 我试图以最可能的方式创建像“复制”这样的简单函数 . 我已经完成了“复制”模式匹配和警卫 . 我无法让它在列表理解中使用 . 我可以想象让列表理解不理想,但我更感兴趣为什么它不起作用=] .
我的问题是:为什么复制'产生[Int]和复制''产生[[Int]],甚至可以用列表理解中的let生成[Int]?
感谢您的时间和帮助:) .
--list comprehension
duplicate' xs = [y | x <- xs, y <- [x,x]]
input => [1,2,3,4]
output => [1,1,2,2,3,3,4,4]
expected? => yes
--list comprehension with let
duplicate'' xs = [y | x <- xs, let y = [x,x]]
input => [1,2,3,4]
output => [[1,1],[2,2],[3,3],[4,4]]
expected? => yes
2 回答
<-
和let
只是意味着不同的东西 .当你写
y <- [x,x]
时,你说的是“依次给列表[x,x]
中的每个值_3040667” .当你写
let y = [x,x]
时,你说“给y
值[x,x]
” .let
除了定义一个新的符号以取一个给定的值之外什么都不做 . 您可以随时手动内联定义:因此只有一个
<-
的任何这样的表达形式这相当于
map f xs
. 因此,结果列表必须始终具有与xs
相同的长度,从而无法实现duplicate
的所需行为:如果要复制,则需要将它们封装为内部列表,这样它们就不会被视为更多元素 .要将这些嵌套列表合并回“扁平”列表,您可以利用列表是monad的事实:
现在,
join
实际上是理论家喜欢定义monad的类别,但正如你可能知道的那样,Haskell的做法有点不同:或者,因为它实际上是相反的定义,
把它放到
duplicate
的修改后的let
版本中:现在,表达式
do { a<-p; b<-q; ... return x }
是monad理解,列表推导的概括 . 它可以改写[x | a<-q, b<-q, ...]
. 对于我们的问题,这是你开始的地方 . 使用纯列表理解时,使用两个
<-
是不可避免的 .当然你还可以随时使用let ...