簡體   English   中英

使用代數數據類型合並列表

[英]Using Algebraic Data Type to combine lists

我試圖了解創建的代數數據類型的語法。 我創建的類型是[Int]Empty ,類似於Maybe with Just and NothingJust必須是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)所說,您有幾個不同的問題。 首先,您需要匹配所有情況,其次,您需要將結果包裝回您的數據類型中,其次,您需要刪除並集中的重復項,其次,您的“設置交集”操作僅適用於關於輸入列表的結構。 unionintersect (在Data.List中也可用)足以用於演示目的而無需調用例如。 Data.IntSet.toList . Data.IntSet.fromList Data.IntSet.toList . Data.IntSet.fromList盡管那樣會更快。 您的版本(如果稍有更正)將輸出出現在兩個列表中相同位置的元素。

關於函子的通用教程通常以Maybe類型開始,這可能對您有所幫助,因為ExampleMaybe [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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM