我想撰寫一個函式來檢查第一個串列是否比第二個串列長并且其中一個可以是無限的。但是我找不到可行的解決方案。
isLonger :: [a] -> [b] -> Bool
isLonger a b
| listLength a > listLength b = True
|otherwise = False
listLength :: [a] -> Integer
listLength = foldr (flip $ const . ( 1)) 0
uj5u.com熱心網友回復:
@dfeuer 的解決方案以聰明取勝,但就更典型的解決方案而言......
評論中提到的一種合理方法是并行處理兩個串列并找出哪個串列首先“用完”——這是較短的串列。一個簡單的解決方案是在兩個串列都非空時進行遞回:
isLonger :: [a] -> [b] -> Bool
isLonger (x:xs) (y:ys) = isLonger xs ys
并在其中一個串列為空時立即回傳答案:
isLonger [] _ = False -- list a <= list b
isLonger _ [] = True -- list a > list b
如果兩個串列同時用完(長度相等),則第一個模式將匹配,因此將在平局的情況下確定答案。
uj5u.com熱心網友回復:
普通的舊自然數無法解決問題,因為您無法在有限時間內計算無限串列的自然數長度。但是,惰性自然數可以做到這一點。
import Data.Function (on)
data Nat = Z | S Nat
deriving (Eq, Ord)
len :: [a] -> Nat
len = foldr (const S) Z
isLonger :: [a] -> [b] -> Bool
isLonger = (>) `on` len
您可以更緊湊地使用串列來表示惰性自然數。
isLonger :: [a] -> [b] -> Bool
isLonger = (>) `on` (() <$)
當然,如果兩個串列都是無限的,那么無論你做什么都注定會陷入無限回圈。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/446777.html
