haskell 将代数数据类型列表转换为实际列表

l5tcr1uw  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(147)

我试图创建一个函数,在其中输入一个代数数据类型列表,它应该输出一个实际的列表。
例如,我们有一个list1 = PCons(GConsEmpty)
输出应为:[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)

我在解决这个问题时遇到了麻烦,如果能得到一些帮助,我将不胜感激!
先谢了!

uxhixvfz

uxhixvfz1#

让我们从数据类型开始:

data Elements = G | S | P deriving (Eq, Show)
data List a = Empty | Cons Elements (List Elements)

从技术的Angular 来看,Elements没有什么问题,但它是一个非常糟糕的名称选择。正如其他人所指出的,更常见的是将类型命名为Element。原因是您的数据类型声明的英语翻译为:
“元素”是金、银或铂。
更有意义的说法是:

**“元素”**为金、银或铂

而且,当你开始用这种类型编写代码时,它开始变得混乱。如果你定义一个Elements类型的值:

e :: Elements
e = P

这代表了一个元素“platinum”,而不是一个集合元素.这种混淆可能会导致你用错误的类型签名写一个list函数,因为你 * 以为 * 你在说list接受一堆Elements,但类型签名 * 实际上 * 说list只接受一个元素.
出于这个原因,我将搜索并替换您的所有代码,我的答案的其余部分将使用“Element“来讨论这个版本:

data Element = G | S | P deriving (Eq, Show)
data List a = Empty | Cons Element (List Element)

list:: Element -> [List]
list Empty = []
list Cons a (List b) = [a] ++ list (List b)

list1 = P `Cons` (G `Cons` Empty)

继续,您的List类型 * 有 * 一个问题:

data List a = Empty | Cons Element (List Element)

你定义了一个参数化类型List a,但是你没有在它的定义中使用参数a。在其他情况下,你看到定义了一个List a,这是因为a参数应该代表列表项的类型。所以同一个列表可以用来保存Element s或Int s或其他数据类型。由于您需要一个只保存Element s的特殊列表数据类型,你应该不带参数写List(在这个声明的左边和右边):

data List = Empty | Cons Element List
        ^^- no "a"                  ^^- no "Element" argument

现在,考虑list的类型签名:

list :: Element -> [List]

list * 应该 * 做的是获取一个元素列表,如下所示:

list1 = P `Cons` (G `Cons` Empty)

并生成一个Haskell列表作为结果:

result1 = [G,P]

但是这个类型签名表示list将接受一个Element并产生一个Haskell列表,其元素的类型为List(即Element的定制List),换句话说,它将产生一个List的元素列表,这当然是不正确的。
实际上,list应该取Element s的List,并返回Element s的(Haskell)列表,因此类型签名应该是:

list :: List -> [Element]

请注意,如果只将类型声明加载到GHCi中,并检查示例参数和结果的类型:

ghci> data Element = G | S | P deriving (Eq, Show)
ghci> data List = Empty | Cons Element List
ghci> :type  P `Cons` (G `Cons` Empty)
P `Cons` (G `Cons` Empty) :: List     -- input is of type `List`
ghci> :type  [G,P]
[G,P] :: [Element]                    -- output is of type `[Element]`

这将确认您需要一个函数List -> [Element]
现在,你的定义还有两个错误:

list Cons a (List b) = [a] ++ list (List b)

Cons a (List b)这样的模式需要用圆括号括起来才能匹配单个参数,因此应该是:

list (Cons a (List b)) = [a] ++ list (List b)

这里还有一个问题,这里使用List没有意义,List是一个类型,它属于类型签名,而不是模式或表达式,至少不是这样,Haskell已经知道Cons的第二个字段是一个List,所以你不需要告诉它,你只需要把这个字段赋给一个变量,如果你从两边去掉List

list (Cons a b) = [a] ++ list b

最后的定义应该键入check:

list :: List -> [Element]
list Empty = []
list (Cons a b) = [a] ++ list b

如果你想以相反的顺序得到结果,只需将连接颠倒过来:

list :: List -> [Element]
list Empty = []
list (Cons a b) = list b ++ [a]

最终代码:

data Element = G | S | P deriving (Eq, Show)
data List = Empty | Cons Element List deriving (Show)

list:: List -> [Element]
list Empty = []
list (Cons a b) = list b ++ [a]

list1 = P `Cons` (G `Cons` Empty)

main = print $ list list1  -- output [G,P]

相关问题