我有一个如此定义的类型:
data People = People [[String]]
和一个如下所示的函数定义:
myFunction :: ([String], People) -> (Int, Int) -> People
myFunction first_tuple second_tuple = filter (myPredicate (fst second_tuple) (fst first_tuple)) (snd first_tuple)
这给了我以下错误:
error:
* Couldn't match expected type `[[String]]'
with actual type `People'
* In the second argument of `filter', namely `(snd first_tuple)'
这让我真正难过,因为我试图用括号尽可能明确地将People
明确定义为[[String]]
。造成这种情况的原因是什么?
以下是myPredicate
的类型签名:
myPredicate :: Int -> [String] -> [String] -> Bool
答案 0 :(得分:3)
首先,函数名称和变量名称必须以小写字母开头。所以
MyFunction
=> myFunction
MyPredicate
=> myPredicate
正如您所定义的
myPredicate :: Int -> [String] -> [String] -> Bool
您在myPredicate
的第三个参数应为[String]
,您在使用该函数时提供People
。filter :: (a -> Bool) -> [a] -> [a]
时使用此功能 - a
专用于[String]
,因此filter
的第二个参数必须为[[String]]
,但您提供People
是不同的东西。
现在你有3个选项
data People..
更改为type People = [[String]]
在函数定义中使用模式匹配
myFunction :: ([String], People) -> (Int, Int) -> People
myFunction (strs,People ps) (x,_) = filter (myPredicate x strs) ps
编写自定义filterPeople
函数
filterPeople :: ([String] -> Bool) -> People -> People
答案 1 :(得分:3)
People
是根据[[String]]
定义的,但与[[String]]
不同,也不可互换。
数据类型声明创建的类型与所有其他类型不同。在这种简单的情况下,People
可以被视为包装和标记的[[String]]
。您需要明确换行和展开才能从People
转到[[String]]
并返回。
非常简单,包装操作拼写为People
:
p = People [["Mary", "Smith"], ["John", "Starke"]]
并且使用模式匹配进行解包:
printPeople (People ppl) = print ppl
如果您想要一个定义为的其他类型的命名类型,请使用类型声明:
type People = [[String]]
在这种情况下,People
与[[String]]
完全同义。