Есть пара вопросов.Во-первых, когда вы пишете:
func4 :: String -> [(Char, Int)]
func4 fun3 = zip (fun3)[length fun3]
* fun3
в этом определении не имеет абсолютного ничего , связанного с ранее определенной вами функцией fun3
.Если вы включили предупреждения компилятора (например, используя флаг -Wall
), он предупредит вас, что привязка для fun3
в этом определении func4
"затеняет" существующую привязку.Это означает, что он обрабатывается так же, как если бы вы использовали полное отдельное имя:
func4 :: String -> [(Char, Int)]
func4 bob = zip (bob) [length bob]
Итак, когда вы оцениваете:
func4 "ccccchhrrre"
функция fun3
неиспользуется на всех.Вместо этого он расширяется по определению func4
до:
func4 "ccccchhrrre"
= zip "ccccchhrrre" [length "ccccchhrrre"]
= zip "ccccchhrrre" [11]
, и поскольку строки в Haskell представляют собой списки символов, это то же самое, что:
= zip ['c','c',...] [11]
Когда вы архивируетедва списка, и один короче другого, застежка-молния заканчивается, когда список заканчивается, поэтому это дает:
= [('c', 11)]
и игнорирует второй и последующие элементы списка символов.
Вместо этого вы, вероятно, хотели написать func4
, чтобы получить строковый аргумент и передать его fun3
:
func4 :: String -> [(Char, Int)]
func4 xs = zip (fun3 xs) [length (fun3 xs)]
К сожалению, это не будет проверкой типа.Проблема в том, что это эквивалентно:
func4 "ccccchhrrre"
= zip ["ccccc","hh","rrr","e"] [length ["ccccc","hh","rrr","e"]]
= zip ["ccccc","hh","rrr","e"] [4]
= [("ccccc", 4)]
с типом [(String, Char)]
вместо ожидаемого [(Char, Char)]
.
Если вы узнали о map
,Вам может быть полезно знать, что:
> map head ["ccccc","hh","rrr","e"]
"chre"
>
и "chre"
эквивалентны списку ['c','h','r','e']
.Если бы вы могли каким-то образом получить список длин [5,2,3,1]
так же, как вы получили список головок, эти списки были бы очень удобными.
Если вы не хотите использовать map
, выможет оказаться полезным написать func4
, который обрабатывает вывод из fun3
, например, так:
> func4 ["ccccc","hh","rrr","e"]
[('c',5),('h',2),('r',3),('e',1)]
>
Он будет иметь немного другую подпись, но структуру, аналогичнуюваш fun3
:
func4 :: [String] -> [(Char, Int)]
func4 [] = []
func4 (str : strs) = ??? : func4 strs
, а затем ваша последняя функция может соединить fun3
и func4
вместе:
rle :: String -> [(Char, Int)]
rle str = func4 (fun3 str)