首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在haskell中实现foreach的初学者/学习者

在haskell中实现foreach的初学者/学习者
EN

Stack Overflow用户
提问于 2011-01-19 23:28:17
回答 4查看 8.5K关注 0票数 7

我正在尝试实现一个foreach态射,以测试我对态射定义和模式匹配的理解。显然,我完全忽略了这两点。

你能纠正我吗?我希望态射foreacha和态射f的列表作为参数,并返回r of f应用于所有a元素的所有结果的列表。

代码语言:javascript
复制
foreach :: [a] → f → [r]
foreach [] f = []
foreach x:[] f = (f x):[]
foreach []:x f = []:(f x)
foreach (x:xs) f = (f x) : (foreach (xs f))

在编译时,我有src\Main.hs:23:0: Parse error in pattern

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-01-19 23:43:42

问题出在语法上,在这一行中:

代码语言:javascript
复制
foreach x:[] f = (f x):[]

模式中的构造函数应用程序通常需要用括号括起来。这将会起作用:

代码语言:javascript
复制
foreach (x:[]) f = (f x):[]

顺便说一下..。函数应用程序的优先级最高,因此在另一方面,您不需要在右侧使用括号:

代码语言:javascript
复制
foreach (x:[]) f = f x:[]

上面的内容适用于任何infix构造函数,但作为最后的说明,特别是对于列表,有一种特殊的语法:

代码语言:javascript
复制
foreach [x] f = [f x]

您的代码还存在其他问题,但这是直接的错误。其他问题的快速概述:

代码语言:javascript
复制
foreach :: [a] → f → [r]

类型变量是隐式通用量化的,因此这意味着任何类型的f。您需要一个更具体的类型,即a -> r

代码语言:javascript
复制
foreach x:[] f = (f x):[]

这是不必要的--这里的递归用例将正确地工作,将f应用于x并在尾部调用自身,从而给出空列表用例。

代码语言:javascript
复制
foreach []:x f = []:(f x)

我不认为这意味着您认为它意味着什么--这是将列表头部与空列表[]进行模式匹配,这意味着该函数正在处理列表列表。

代码语言:javascript
复制
foreach (x:xs) f = (f x) : (foreach (xs f))

此处的括号不是不必要的,就是不正确的。同样,函数应用程序比:等运算符具有更高的优先级。此外,(xs f)意味着将xs应用于f,就好像它是一个函数一样。要对两个参数应用foreach,只需使用foreach xs f即可。

为了便于比较,下面是标准库函数map的源代码(除了参数顺序不同)

代码语言:javascript
复制
map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs
票数 13
EN

Stack Overflow用户

发布于 2011-01-19 23:52:29

您给出的类型签名(至少在Haskell编译器看来)是假的。它是一个函数,可以获取任意a的项列表和任意类型f的值,并生成任意类型r的值列表。这就像在说:“我有一群大象和一把螺丝刀,把每一头大象都变成芒果”。

您的目标似乎是实现map函数:

代码语言:javascript
复制
map :: (a -> b) -> [a] -> [b]

当然,颠倒论点是完全有效的:

代码语言:javascript
复制
foreach :: [a] -> (a -> b) -> [b]

您的实现非常接近,但有一些问题。

最重要的是要记住,你使用的是列表,而不是数组。cons运算符,也称为“:”,获取一个项目并将其添加到一个列表(例如1 : [2,3,4])。您不能像在[]:(f x)中那样,使用它来任意连接项目和列表。有连接两个列表的++运算符(例如,[f x] ++ xs,它与(f x) : xs相同),但您不应该需要它来实现foreach

最后,(foreach (xs f))并没有做您认为它所做的事情。它不像C风格语言中的foreach(xs,f),它像foreach(xs(f))(xs f)本身就像使用xs作为函数并应用f作为参数。相反,您需要(foreach xs f)

我将停在这里,以避免透露太多信息。不过有一个小花招:函数应用程序比任何操作符都具有更高的优先级,所以你可以说f x : foreach xs f而不是(f x) : (foreach xs f)

票数 3
EN

Stack Overflow用户

发布于 2011-01-19 23:41:24

您忘记了将()放在foreach []:x f = []:(f x)中,并且错误地指定了函数类型,现在应该编译以下代码:

代码语言:javascript
复制
foreach :: [a] -> (a -> r) -> [r]
foreach [] f = []
foreach (x:[]) f = (f x):[]
foreach (x:xs) f = (f x) : (foreach xs f)

然后运行:

代码语言:javascript
复制
*Main> foreach [1..20] (+1)
[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4737092

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档