我需要創建一個接受字串和解碼規則的函式。它應該更改字串中的字符,直到根據解碼規則無法更改為止。每次我得到字串和解碼規則(首先是什么變化,第二是什么)。例如:
string = "JCEJ"
rules = [('E',"GZ"),('F',"HK"),('C',"EF"),('J',"CC")]
并且輸出應該是"GZHKGZHKGZHKGZGZHKGZHK"
(規則設定為 1 個字符和 2 個字符)
我很迷茫,我試圖創建所有可能的組合,然后根據規則生成串列。這是我的嘗試。
rules = [('E',"GZ"),('F',"HK"),('C',"EF"),('J',"CC")]
string = "JCEJ"
combinations = [(x,y,z) | x <- [ch | ch <- string], y <- [x | (x,y) <- rules], z <- [y | (x,y) <- rules]]
generate = [z | (x,y,z) <- combinations, if x == y then z else x]
錯誤資訊:
decoder.hs:8:57: error:
? Couldn't match expected type ‘Bool’ with actual type ‘[Char]’
? In the expression: z
In the expression: if x == y then z else x
In a stmt of a list comprehension: if x == y then z else x
|
8 | generate = [z | (x,y,z) <- combinations, if x == y then z else x]
| ^
decoder.hs:8:64: error:
? Couldn't match expected type ‘Bool’ with actual type ‘Char’
? In the expression: x
In the expression: if x == y then z else x
In a stmt of a list comprehension: if x == y then z else x
|
8 | generate = [z | (x,y,z) <- combinations, if x == y then z else x]
| ^
uj5u.com熱心網友回復:
免責宣告:這一切都不像它可能的那樣漂亮。
你有一個查找表rules。Haskell 有一個方便的lookup功能:
ghci> :t lookup
lookup :: Eq a => a -> [(a, b)] -> Maybe b
我們可以在字串上折疊查找:
ghci> foldr (\x i -> case lookup x rules of {Just s -> s i; _ -> (x:i)}) "" "EF"
"GZHK"
讓我們稱之為singlePassDecode:
singlePassDecode :: Foldable t => t Char -> [(Char, [Char])] -> [Char]
singlePassDecode s rules = foldr update "" s
where
update ch acc =
case lookup ch rules of
Just s' -> s' acc
Nothing -> ch : ""
但一次通過并不一定能完成作業。我們需要遞回呼叫它,直到沒有任何轉換可以執行。這意味著我們需要知道輸入字串中的任何字符是否在查找表中。
剩下的...就是填寫正確的遞回呼叫,以避免提供完整的答案。
decode :: [Char] -> [(Char, [Char])] -> [Char]
decode s rules
| any (\ch -> elem ch (map fst rules)) s = ...
| otherwise = s
第一個條件也可以表示如下。
any (flip elem $ map fst rules) s
uj5u.com熱心網友回復:
AString是Chars 的串列,因此[ch | ch <- string]不需要 。
您在這里用 定義了一些內部串列推導x,但這x是一個更區域范圍的變數,而x不是xin x <- [ ch | ch <- str]。
你可以做一個過濾條件來過濾,所以:
generate = concat [ y | x <- string, (x', y) <- rules, … ]
這…是您需要填寫的部分。它需要與x比較x'。
uj5u.com熱心網友回復:
您的規則串列描述了從一個Char到兩個Chars(如果匹配)或一個Char(原始輸入,如果沒有匹配)的映射。我們可以通過總是回傳 a 來處理這兩種情況[Char],并且我們可以推廣到任何a而不是特定于Char:
import Data.Maybe (fromMaybe)
transform :: Eq a => [(a, [a])] -> a -> [a]
transform rules x = fromMaybe [x] (lookup x rules)
由于此映射不依賴于其他背景關系,因此concatMap(也拼寫為(>>=))是在輸入串列中應用它并連接結果的好工具。
transformAll :: Eq a => [(a, [a])] -> [a] -> [a]
transformAll rules = concatMap (transform rules)
-- or, transformAll = concatMap . transform
擁有一個重復應用一個函式直到它沒有改變的函式也很有用:
fixPoint :: Eq a => (a -> a) -> a -> a
fixPoint f x | x == x' = x
| otherwise = fixPoint f x'
where x' = f x
然后剩下的就是結合我們的工具:
transformStringRepeatedly :: Eq a => [(a, [a])] -> [a] -> [a]
transformStringRepeatedly rules = fixPoint (transformAll rules)
-- or, transformStringRepeatedly = fixPoint . transformAll
main = print (transformStringRepeatedly [('E',"GZ"),('F',"HK"),('C',"EF"),('J',"CC")] "JCEJ")
我們可以看到它產生了您期望的答案:
$ runghc tmp.hs
"GZHKGZHKGZHKGZGZHKGZHK"
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/524443.html
標籤:细绳列表哈斯克尔字符
