我有一個資料型別,我的作業是使用一個函式data Weather = Sunny | Cloudy | Rainy deriving (Show, Eq)只對非雨天進行分組。[Weather] -> [[Weather]]
假設我有一個這樣的串列:
[Rainy, Cloudy, Sunny, Sunny, Cloudy, Rainy, Rainy, Sunny, Cloudy, Sunny, Cloudy, Rainy, Sunny]Sunny,我想把它變成一個只包含orCloudy天的串列,如下所示:
[[Cloudy, Sunny, Sunny, Cloudy], [Sunny, Cloudy, Sunny, Cloudy], [Sunny]].
我被禁止splitOn使用Data.List.Split.
我試圖解決這個問題:
groupNotRainy :: [Weather] -> [[Weather]]
groupNotRainy [] = [[]]
groupNotRainy [x]
| x /= Rainy = [[x]]
| otherwise = [[]]
groupNotRainy [x,y]
| x == Rainy = [[y]]
| y == Rainy = [[x]]
| otherwise = [[x,y]]
groupNotRainy (x:y:xs)
| y == Rainy = [[x], groupNotRainy xs]
這給了我一個Couldn't match type ‘[Weather]’ with ‘Weather’錯誤。
uj5u.com熱心網友回復:
你已經接近解決方案了。為了進行型別檢查,您的代碼末尾應更改如下:
groupNotRainy (x:y:xs)
| y == Rainy = [x] : (groupNotRainy xs)
| otherwise = ...TODO...
因為型別groupNotRainy xs是[[Weather]]。
您的以下模式恰好與空 xs 重疊:
groupNotRainy [x,y]
groupNotRainy (x:y:xs)
所以最好只保留第二個。在那里,您有 2 個布林值要測驗。我認為最簡單/最干凈(如果不是最短)的方法就是列舉 4 種情況:
groupNotRainy [] = []
groupNotRainy [x]
| x /= Rainy = [[x]]
| otherwise = []
groupNotRainy (x:y:xs)
| x == Rainy && y == Rainy = groupNotRainy xs
| x /= Rainy && y == Rainy = [x] : (groupNotRainy xs)
| x == Rainy && y /= Rainy = groupNotRainy (y:xs)
| otherwise {- both non-rainy -} = let yss = groupNotRainy (y:xs)
in (x : head yss) : tail yss
如果 x 和 y 都正常(非下雨),則計算 y:xs 的函式結果,然后將 x 附加到該結果中的第一個串列(必須非空)。
請注意最后一個子句是otherwise. 編譯器不是無所不知的,如果它只是| (p x) && (p y).
此外,定義通用函式可能更慣用:
grouper :: (a -> Bool) -> [a] -> [[a]]
grouper p [] = []
grouper p [x]
| (p x) = [[x]]
| otherwise = []
grouper p (x:y:xs)
| (not $ p x) && (not $ p y) = grouper p xs
| ( p x) && (not $ p y) = [x] : (grouper p xs)
| (not $ p x) && ( p y) = grouper p (y:xs)
| otherwise {- both x y OK -} = let yss = grouper p (y:xs) -- not empty
in (x : head yss) : tail yss
然后groupNotRainy通過柯里化定義,也稱為“部分應用”:
groupNotRainy :: [Weather] -> [[Weather]]
groupNotRainy = grouper (/= Rainy)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/412892.html
標籤:
下一篇:Haskell中的基本函子
