Haskell - 函数'length'不适用于自定义数据类型

时间:2015-10-28 15:11:56

标签: haskell

我是Haskell的新手,我需要定义这种数据类型:

numberOfEmployees :: Restaurant -> Int
numberOfEmployees rest = length rest

这是餐馆员工的名单:(每个员工的姓名,地址,工资)。

现在,我正在尝试定义 numberOfEmployees 函数:

type Restaurant = [(String, String, Int)]

但是我得到了这个编译错误: 无法将预期类型't2 a0'与实际类型'Restaurant'匹配

如果我使用类型而不是数据,为什么会有效? (我不能在我的代码中使用'type'声明,因为它是关于'data'的练习的一部分)

     <div class="item item1 wheat">a.</div><!--
  --><div class="item item2 pink">a.</div><!--
  --><div class="item item3 beige">a.</div><!--
  --><div class="item item4 gainsboro">a.</div>

3 个答案:

答案 0 :(得分:9)

  

为什么我使用type而不是数据?

因为type是弱别名。在代码中,它等同于RHS上的类型。

另一方面,

data(和newtype,或许更是如此)会创建一个“强”别名,这意味着您需要首先解压缩它:

numberOfEmployees :: Restaurant -> Int
numberOfEmployees (Restaurant rest) = length rest

如果要限制对数据的操作,这一点尤为重要。如果内部模块不导出构造函数,则用户只能使用智能构造函数和其他运算符,并且无法直接访问或修改包装数据(有效地使其不透明)。

答案 1 :(得分:1)

函数length的类型为[a] -> Int。那就是它需要一个列表作为参数。但是你试图将Restaurant传递给它。

您应该使用模式匹配来获取列表,并将其传递给length

numberOfEmployees :: Restaurant -> Int
numberOfEmployees (Restaurant a) = length a

答案 2 :(得分:1)

length的类型是

length :: Foldable t => t a -> Int

但是没有类型taRestaurant类型等于t a。正如其他人所解释的那样,您需要提取列表并找到列表的长度 - Restaurant永远不会有length

挑剔

你可以写

type Foo a = Restaurant

那样

Foo a ~ Restaurant
每个a

。但是,Foo只是类型同义词/系列,而不是正确的第一类。只有使用datanewtype声明的真正类型,内置的(),列表和元组类型,奇怪的->以及这些类型的应用程序才真正有用。