'x'定义为'y',但编译器不能将'y'与'x'匹配,为什么?

时间:2017-08-27 13:14:29

标签: haskell

我有一个如此定义的类型:

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

2 个答案:

答案 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个选项

  1. data People..更改为type People = [[String]]
  2. 在函数定义中使用模式匹配

    myFunction :: ([String], People) -> (Int, Int) -> People
    myFunction (strs,People ps) (x,_) = filter (myPredicate x strs) ps
    
  3. 编写自定义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]]完全同义。