我正在尝试实现一个foreach态射,以测试我对态射定义和模式匹配的理解。显然,我完全忽略了这两点。
你能纠正我吗?我希望态射foreach以a和态射f的列表作为参数,并返回r of f应用于所有a元素的所有结果的列表。
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
发布于 2011-01-19 23:43:42
问题出在语法上,在这一行中:
foreach x:[] f = (f x):[]模式中的构造函数应用程序通常需要用括号括起来。这将会起作用:
foreach (x:[]) f = (f x):[]顺便说一下..。函数应用程序的优先级最高,因此在另一方面,您不需要在右侧使用括号:
foreach (x:[]) f = f x:[]上面的内容适用于任何infix构造函数,但作为最后的说明,特别是对于列表,有一种特殊的语法:
foreach [x] f = [f x]您的代码还存在其他问题,但这是直接的错误。其他问题的快速概述:
foreach :: [a] → f → [r]类型变量是隐式通用量化的,因此这意味着任何类型的f。您需要一个更具体的类型,即a -> r。
foreach x:[] f = (f x):[]这是不必要的--这里的递归用例将正确地工作,将f应用于x并在尾部调用自身,从而给出空列表用例。
foreach []:x f = []:(f x)我不认为这意味着您认为它意味着什么--这是将列表头部与空列表[]进行模式匹配,这意味着该函数正在处理列表列表。
foreach (x:xs) f = (f x) : (foreach (xs f))此处的括号不是不必要的,就是不正确的。同样,函数应用程序比:等运算符具有更高的优先级。此外,(xs f)意味着将xs应用于f,就好像它是一个函数一样。要对两个参数应用foreach,只需使用foreach xs f即可。
为了便于比较,下面是标准库函数map的源代码(除了参数顺序不同)
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs发布于 2011-01-19 23:52:29
您给出的类型签名(至少在Haskell编译器看来)是假的。它是一个函数,可以获取任意a的项列表和任意类型f的值,并生成任意类型r的值列表。这就像在说:“我有一群大象和一把螺丝刀,把每一头大象都变成芒果”。
您的目标似乎是实现map函数:
map :: (a -> b) -> [a] -> [b]当然,颠倒论点是完全有效的:
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)。
发布于 2011-01-19 23:41:24
您忘记了将()放在foreach []:x f = []:(f x)中,并且错误地指定了函数类型,现在应该编译以下代码:
foreach :: [a] -> (a -> r) -> [r]
foreach [] f = []
foreach (x:[]) f = (f x):[]
foreach (x:xs) f = (f x) : (foreach xs f)然后运行:
*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]https://stackoverflow.com/questions/4737092
复制相似问题