簡體   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