我试图创建一个函数,在其中输入一个代数数据类型列表,它应该输出一个实际的列表。
例如,我们有一个list1 = P
Cons(G
ConsEmpty)
输出应为:[G,P]
我创建了以下代数数据类型:
data Elements = G | S | P deriving (Eq, Show)
data List a = Empty | Cons Elements (List Elements)
我现在的职务是
list:: Elements -> [List]
list Empty = []
list Cons a (List b) = [a] ++ list (List b)
我在解决这个问题时遇到了麻烦,如果能得到一些帮助,我将不胜感激!
先谢了!
1条答案
按热度按时间uxhixvfz1#
让我们从数据类型开始:
从技术的Angular 来看,
Elements
没有什么问题,但它是一个非常糟糕的名称选择。正如其他人所指出的,更常见的是将类型命名为Element
。原因是您的数据类型声明的英语翻译为:“元素”是金、银或铂。
更有意义的说法是:
**“元素”**为金、银或铂
而且,当你开始用这种类型编写代码时,它开始变得混乱。如果你定义一个
Elements
类型的值:这代表了一个元素“platinum”,而不是一个集合元素.这种混淆可能会导致你用错误的类型签名写一个
list
函数,因为你 * 以为 * 你在说list
接受一堆Elements
,但类型签名 * 实际上 * 说list
只接受一个元素.出于这个原因,我将搜索并替换您的所有代码,我的答案的其余部分将使用“
Element
“来讨论这个版本:继续,您的
List
类型 * 有 * 一个问题:你定义了一个参数化类型
List a
,但是你没有在它的定义中使用参数a
。在其他情况下,你看到定义了一个List a
,这是因为a
参数应该代表列表项的类型。所以同一个列表可以用来保存Element
s或Int
s或其他数据类型。由于您需要一个只保存Element
s的特殊列表数据类型,你应该不带参数写List
(在这个声明的左边和右边):现在,考虑
list
的类型签名:list
* 应该 * 做的是获取一个元素列表,如下所示:并生成一个Haskell列表作为结果:
但是这个类型签名表示
list
将接受一个Element
并产生一个Haskell列表,其元素的类型为List
(即Element
的定制List
),换句话说,它将产生一个List
的元素列表,这当然是不正确的。实际上,
list
应该取Element
s的List
,并返回Element
s的(Haskell)列表,因此类型签名应该是:请注意,如果只将类型声明加载到GHCi中,并检查示例参数和结果的类型:
这将确认您需要一个函数
List -> [Element]
。现在,你的定义还有两个错误:
像
Cons a (List b)
这样的模式需要用圆括号括起来才能匹配单个参数,因此应该是:这里还有一个问题,这里使用
List
没有意义,List
是一个类型,它属于类型签名,而不是模式或表达式,至少不是这样,Haskell已经知道Cons
的第二个字段是一个List
,所以你不需要告诉它,你只需要把这个字段赋给一个变量,如果你从两边去掉List
:最后的定义应该键入check:
如果你想以相反的顺序得到结果,只需将连接颠倒过来:
最终代码: