繁体   English   中英

代数数据类型列表到实际列表

[英]Algebraic data type list into an actual list

我想创建一个函数,在其中输入一个代数数据类型列表,它应该输出一个实际列表。

例如,我们有一个list1 = P `Cons` (G `Cons` Empty)

输出应为: [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)

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

提前致谢!

让我们从您的数据类型开始:

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

从技术角度来看, Elements没有任何问题,但它是一个非常糟糕的名称选择。 正如其他人所指出的,命名类型Element更为常见。 原因是你的数据类型声明的英文翻译是:

“元素”是黄金或白银或铂金。

什么时候说:

“元素”是金或银或铂金

此外,当您开始使用这种类型编写代码时,它会开始变得混乱。 如果您定义Elements类型的值:

e :: Elements
e = P

这代表单个元素“白金”,而不是集合元素。 这种混淆可能会导致您使用错误的类型签名编写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的特殊列表数据类型,因此您应该编写不带参数的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元素。 这肯定是不对的。

事实上, list应该采用ElementList并返回Element的(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

最终定义应该进行类型检查:

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]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM