簡體   English   中英

Haskell多態函數,用於檢查列表是否為回文

[英]Haskell polymorphic function that checks if a list is palindrome

我正在嘗試解決這一問題,但我想不出解決方案。 考慮以下因素,我需要檢查列表是否為回文式:
如果列表很簡單,我只需要檢查水平回文,如果它是嵌套列表,則需要同時檢查垂直和水平。
我還需要記住,列表中的每個元素本身都必須是回文,例如:

A = [1,2,3,3,2,1]是回文

對於這種情況,我只創建了一個使用反向的函數:

unidimensional:: (Eq a) => [a] -> Bool
unidimensional [] = error"List is empty."
unidimensional xs = xs == reverse xs

同樣是這種情況,例如:

B = [[1,2,1],[1,2,1]]水平回文,並檢查它是否垂直回文,我只是將其轉置, [[1,1],[2,2],[1,1 ]] ,結果是,都是回文。

我通過使用轉置函數垂直評估回文率,然后使用在檢查水平回文率之前使用的一維函數解決了所有問題:

--Checks if it's palindrome horizontally and vertically 
bidimensional:: (Eq a) => [[a]] -> Bool
bidimensional [[]] = error"Empty List."
bidimensional (xs) = if left_right xs && up_down xs then True else False
--Checks if it's palindrome horizontally:
left_right (x:xs) = if x == reverse x then
if xs /= [] then bidimensional xs else True 
else False
--Checks if it's palindrome vertically:
up_down:: (Eq a) => [[a]] -> Bool
up_down (xs) = left_right ys where ys = transpose xs
transpose:: [[a]]->[[a]]
transpose ([]:_) = []
transpose x = (map head x) : transpose (map tail x)



問題在這里:

我的程序需要接收的輸入必須是這樣的:

> palindrome [[1,2,2,1], [3,7,9,9],[3,7,9,9], [1,2,2,1]]

我的問題是:我的函數回文應接收列表[a]作為參數,但是回文應對嵌套列表起作用,例如[[[a]]][[a]]

回文是接受輸入的功能。

問題是,當我得到一個簡單列表時,我的頭(即x是一個數字,而xs是尾部)將是其余的數字,這沒關系,但是當回文式收到一個嵌套列表時,例如[[[[2,2],[2,2]],[[1,1],[1,1]]]的頭部, x現在是[[2,2],[2,2]] ,所以我不能用我的功能一樣,二維因為[2,2],[2,2]是不是一個列表了,當我嘗試調用二維與XS[2,2],[2, 2]]我收到一個錯誤: xs現在輸入a而不是[[a]]

我的問題是 :考慮到我之前提到的錯誤,我該如何使我的函數回文功能與任何類型的列表一起使用(簡單和嵌套)。 提前致謝!

我的問題是:考慮到我之前提到的錯誤,我如何使我的函數回文符能夠與任何類型的列表一起使用(簡單和嵌套)。 提前致謝!

讓我們考慮一下這種假設的palindrome功能,並嘗試找出它需要哪種類型的簽名。 (從函數的類型簽名方面考慮函數總是有幫助的。)

假設palindrome具有簽名palindrome :: [x] -> Bool

我們下面的陳述是正確的:

palindrome [1, 2, 1] === True
palindrome [1, 2, 2] === False
palindrome [[1, 2, 1], [3, 4, 3], [1, 2, 1]] === True
palindrome [[1, 2, 2], [3, 4, 3], [1, 2, 2]] === False

在前兩個斷言中, palindrome專精於[Integer] -> Bool ,因此在這些情況下xInteger x === Integer的唯一明智的實現只是檢查所提供的整數列表是否是回文,即檢查第一個元素是否等於最后一個元素,彈出並重復(或等效地,檢查xs等於reverse xs )。 每當xEq的實例時,我們都可以使用此算法。

在最后兩個屬性中, palindrome[[Integer]] -> Bool ,因此x在此處是[Integer] 看來我們應該能夠檢測到x本身是一個整數列表,然后知道我們需要對每個內部列表遞歸應用回文。 但是,Haskell多態不能那樣工作。 為了使函數在類型參數x上具有多態性,我們需要定義該函數的單個實現, 無論x是什么類型 ,其實現方式都相同。

換句話說,要定義多態函數palindrome :: [x] -> Bool ,我們的實現不能知道有關類型參數x任何信息。 這迫使我們使用相同的實現時, x === [Integer]因為我們使用時, x === Integer ,這將評估為True而不是False的最后測試案例。

如果堅持輸入為標准[]類型,則將無法使palindrome函數按您希望的方式在Haskell中的嵌套列表中使用。

您可能要做的一件事是讓palindrome功能接受一個額外的Int類型的參數,該參數告訴該功能進行檢查的深度。 在這種情況下,您需要提前知道輸入的嵌套深度。 您可能要做的另一件事是編寫palindrome函數以在[]之外的其他數據結構中接受輸入,例如Tree或具有任意嵌套的內容。 也許您可以編寫函數來接受Value ,該類型表示流行的庫Aeson中的任意JSON值。

注意:palindrome []設為True可能是個好主意,不是嗎?

您可以使用類型類。

class Palindrome a where
  palindrome :: a -> Bool

instance Palindrome Integer where
  palindrome _ = True

instance (Eq a, Palindrome a) => Palindrome [a] where
  palindrome xs = xs == reverse xs && all palindrome xs

對於二維列表,您正在檢查列表是否是“水平和垂直”回文。 這可以在沒有transpose功能的情況下完成:如果列表是回文,則列表是“垂直”回文,如果每個子列表都是回文,則列表是“水平”回文。 第二個instance檢查兩者。

對於一維列表,第二個instance僅檢查列表是否為回文。 在這種情況下, && all palindrome xs也可能不存在:由於第一個instance指定Integer始終是回文,因此all palindrome xs總是求值為True 這可以看作是此遞歸算法的“基本情況”。

這將適用於任何深度的嵌套列表。 您還可以實例化其他基本數據類型的類,或者甚至可以對所有類型的Eq類實例化(盡管我很確定)(盡管這會導致實例重疊,這是蠕蟲自身的行為)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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