微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Haskell 列表理解和列表 Monad

如何解决Haskell 列表理解和列表 Monad

我正在尝试编写一些自定义类型 Martix a,它基本上是列表 [[a]] 的列表。当我尝试实现一个名为 colAt函数时,它应该给出矩阵的垂直元素,我首先使用了列表推导式:

colAt :: Int -> Matrix a -> [a]
colAt c m = [ e | r <- m,e <- r !! c ]

但 Ghci 告诉我

Occurs check: cannot construct the infinite type: a ~ [a]
In the expression: r !! c

虽然 do 符号与此完美配合

colAt :: Int -> Matrix a -> [a]
colAt c m = do
    r <- m
    return (r !! c)

是什么导致了这个错误?我认为基本上列表理解是列表符号的语法糖,但鉴于此错误,我的理解是错误的?

解决方法

您的理解完全正确:列表推导式确实只是 do 表示法的语法糖!问题是您没有正确地对列表理解进行脱糖。

首先,让我们重复列表推导以供参考:

colAt :: Int -> Matrix a -> [a]
colAt c m = [ e | r <- m,e <- r !! c ]

现在,我将部分脱糖,将 r <- m 位移到理解之外:

colAt :: Int -> Matrix a -> [a]
colAt c m = do
    r <- m
    [e | e <- r !! c]

这很容易完全脱糖:

colAt :: Int -> Matrix a -> [a]
colAt c m = do
    r <- m
    e <- r !! c
    e

比较正确的实现:

colAt :: Int -> Matrix a -> [a]
colAt c m = do
    r <- m
    return (r !! c)

这里的问题现在很明显。在正确的实现中采用 m,然后对于每个项目 r <- m 依次找到元素 r !! c :: a,将其包装在一个列表中,然后返回它。相比之下,您的实现正确提取每个项目 r <- m,然后尝试提取“列表”r !! c :: a 的每个“元素”——实际上不一定是列表,给出了您看到的类型错误.修复很简单:在正确的实现中,只需添加一个 return,给出 [ e | r <- m,e <- return (r !! c) ]。或者,更简单地说,利用 [x | x <- return l][l] 相同的事实,您可以更简单地将其重写为 [ r !! c | r <- m ]

,

如果你写 e <- r !! c,它期望 r !! c 是一个列表,因为你正在枚举该列表,但 r !! c 是一个项目(类型为 a) ,因此这仅在您使用 Matrix [a] 时才有效。

这里不需要枚举,可以将r !! c移到“yield”部分:

colAt :: Int -> Matrix a -> [a]
colAt c m = [ r !! c | r <- m ]

但是你在这里做的是一个映射,所以你可以使用 map :: (a -> b) -> [a] -> [b]:

colAt :: Int -> Matrix a -> [a]
colAt c = map (!! c)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?