Понимание проблемы
toStr :: (Num a) => [a] -> String
toStr (x:xs)
| length xs == 0 = []
| length xs > 0 = show x : toStr xs
^ ^ ^
This is a String | |
| This is a String
This is a function of type String -> [String] -> [String]
Итак, у вас есть:
show x
, что является String
toStr xs
, что является String
- Функция
:
, которая ожидает String
и [String]
.
Это несогласие по toStr xs
является строкой, но ожидалось, что :
быть списком строк - это суть проблемы. Вы хотели объединить ваши строки в одну строку (show x ++ toStr xs
).
Понимание следующей проблемы *
Теперь у вас должно быть несколько других проблем. Во-первых, у вас есть Num a => a
, который вы пытаетесь show
. Функция show
не является частью Num
, а вместо этого входит в класс Show
, поэтому измените Num a =>
на Show a =>
.
Наконец, этот код не очень хорошо обрабатывает случай пустого списка:
toStr (x:xs)
| length xs == 0 = []
Заметив, что после x
ничего не происходит, этот код будет игнорировать последнее значение x
и вернет пустой список. Он не обрабатывает случай, когда нет «последнего элемента», и все, что у вас есть, это пустой список Чтобы справиться с этим, попробуйте toStr [] = []
.
Собираем все вместе
toStr :: (Show a) => [a] -> String
toStr [] = []
toStr (x:xs) = show x ++ toStr xs
с результатом:
> toStr [1,0,0,1,1]
"10011"
Идиоматический код
Выше приведен хороший результат, но примитивные рекурсивные функции обычно не нужны при написании Haskell. Большинство операций типа данных map
или fold
. В этом случае это отображение функции show
(обратите внимание, как она show
использует каждый элемент) и fold
функции ++
- также известной как конкатенация строк.
toStr2 xs = foldr (++) "" (map show xs)
-- > toStr2 [1,0,0,1,1]
-- "10011"
Даже это можно еще больше упростить. Так часто встречается специальная функция concatMap
:
toStr3 xs = concatMap show xs
То, что мы можем «сократить» (убрать большинство внешних аргументов из определения / приложения функции - думайте с точки зрения определения функции как другой функции, а не значений, которые она произвела):
toStr4 = concatMap show
В качестве альтернативы, мы можем заново получить исходный глагол сгиба и карты. Функция concatMap
- это просто определенный тип fold
+ map
, который работает со списками. Существует более общий foldMap
, который работает с любой функцией, которая производит моноид (и списки являются одной из таких структур, что означает, что так же как и строки, так как они являются списками символов):
toStr5 = foldMap show