[英]Using Algebraic Data Type to combine lists
我試圖了解創建的代數數據類型的語法。 我創建的類型是[Int]
或Empty
,類似於Maybe
with Just
and Nothing
, Just
必須是Int
的列表。 當它接受兩個輸入並給出相同類型的輸出時,我很難理解如何操縱創建的類型。
data Example = Arg [Int]
| Empty
deriving Show
我使用模式匹配,並且了解每種情況都必須解決。 但是,我的問題來自最終模式的語法,其中兩種模式都不是Empty
。 我正在嘗試編寫兩個函數:一個合並了Example
構造函數中的兩個[Int]
列表的函數,並且我想創建一個僅顯示兩者共享而不共享的[Int]
集合的函數。
第一個問題是結合兩組。 我可以使用常規函數來執行此操作,但是在某個地方使用Example
數據類型可以關閉語法,並且我不熟悉它。 第二個最大的問題是相同的:我理解遞歸,但是我不理解在創建的數據類型中遞歸的語法。 我也在考慮在第二個函數中使用where
語句,但是如果我不能正確獲取基本遞歸的語法,那么我懷疑它會成功。
combine :: Example -> Example -> Example
combine Empty Empty = Empty
combine (Arg xs) Empty = (Arg xs)
combine Empty (Arg ys) = (Arg ys)
combine (Arg xs) (Arg ys) = Arg xs ++ ys
same :: Example -> Example -> Example
same _ Empty = Empty
same Empty _ = Empty
same (Arg x : xs) (Arg y : ys)
| x == y = x
| otherwise = same (Arg xs) (Arg ys)
的輸出combine
應當是[Int]
包含所有列表Int
從兩個列表秒; 如果一個列表為空,則應返回整個非空列表集。
same
的輸出應包含一個[Int]
列表,該列表僅包含兩個組共享的數字,並且不重復。 如果一組為空,則輸出為空。
combine :: Example -> Example -> Example
combine x Empty = x
combine Empty x = x
combine (Arg xs) (Arg ys) = Arg $ union xs ys
union xs ys = nub $ xs ++ ys
nub [] = []
nub (x:xs) = if x `elem` xs then nub xs else x : nub xs
same :: Example -> Example -> Example
same _ Empty = Empty
same Empty _ = Empty
same (Arg xs) (Arg ys) = Arg $ intersect xs ys
intersect _ [] = [] -- unnecessary but practical!
intersect [] _ = []
intersect (x:xs) ys = if x `elem` ys then x : intersect xs ys else intersect xs ys
正如羅賓(Robin)所說,您有幾個不同的問題。 首先,您需要匹配所有情況,其次,您需要將結果包裝回您的數據類型中,其次,您需要刪除並集中的重復項,其次,您的“設置交集”操作僅適用於關於輸入列表的結構。 union
, intersect
(在Data.List中也可用)足以用於演示目的而無需調用例如。 Data.IntSet.toList . Data.IntSet.fromList
Data.IntSet.toList . Data.IntSet.fromList
盡管那樣會更快。 您的版本(如果稍有更正)將輸出出現在兩個列表中相同位置的元素。
關於函子的通用教程通常以Maybe
類型開始,這可能對您有所幫助,因為Example
與Maybe [Int]
同構。
您可能要使用Arg (x : xs)
解構函數的示例是一個函數,該函數在兩個列表的每個索引處采用較小的元素。 你能嘗試自己遞歸地寫那個嗎,即。 不使用zip
嗎?
編輯:重大更改和更正
使用提升的概念,我想到了這個解決方案:
import Data.List (nub)
data Example = Arg [Int]
| Empty
deriving Show
combine :: Example -> Example -> Example
combine Empty Empty = Empty
combine x Empty = x
combine Empty x = x
combine (Arg xs) (Arg ys) = Arg $ nub $ xs ++ ys
same :: Example -> Example -> Example
same arg1 arg2 = lift nub $ same' arg1 arg2
where
same' _ Empty = Empty
same' Empty _ = Empty
same' (Arg []) y = Arg []
same' (Arg (x : xs)) (Arg (ys))
| x `elem` ys = lift (x : ) $ same' (Arg xs) (Arg ys)
| otherwise = same' (Arg xs) (Arg ys)
lift :: ([Int] -> [Int]) -> Example -> Example
lift _ Empty = Empty
lift f (Arg x) = Arg (f x)
lift
作用是將一個函數應用於Arg
的“內容”。 如果您具有same (Arg [1, 2, 4, 3]) (Arg [3,1,4])
的表達式same (Arg [1, 2, 4, 3]) (Arg [3,1,4])
則遞歸會將其轉換為:
lift nub $ lift (1 : ) $ lift (4 : ) $ lift (3 : ) $ Arg []
wich計算如下:
lift nub $ lift (1 : ) $ lift (4 : ) $ Arg (3:[])
lift nub $ lift (1 : ) $ Arg (4:3:[])
lift nub $ Arg (1:4:3:[])
Arg (nub $ 1:4:3:[])
然后最后:
Arg [1,4,3]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.