Классическая ошибка - вызывать такую функцию, как f (x1, x2)
. В функциях Haskell есть один параметр, и часто это , а не кортеж.
Ваша fooHelper
функция имеет тип:
fooHelp :: String -> (Int -> String)
так что это функция, которая принимает String
, и возвращает функцию, которая отображает Int
s на String
s. Таким образом, вы должны вызвать функцию как:
(fooHelp x) (read $ charToString( xs !! 0 ) :: Int)
или менее подробный:
(fooHelp x) (read $ charToString( xs !! 0 ) :: Int)
Но теперь типы все еще не совпадают: x
- это Char
, а не String
, вы можете заключить его в список, например:
fooHelp [x] (read $ charToString( xs !! 0 ) :: Int)
как:
foo :: String -> String
foo (x:xs) = let curent = fooHelp [x] (read $ charToString( xs !! 0 ) :: Int)
in x : (curent) ++ foo (tail xs)
Но, тем не менее, у этой функции есть проблема: мы перебираем строку, так что в итоге мы получим пустую строку, и у foo
нет для этого случая. В этом случае нам нужно вернуть пустую строку, например:
foo :: String -> String
foo (x:xs) = let curent = fooHelp [x] (read $ charToString( xs !! 0 ) :: Int)
in x : (curent) ++ foo (tail xs)
foo [] = ""
Но это все еще не очень элегантно. Здесь мы выполняем много ненужных операций, таких как перенос символов в строки и т. Д.
Мы можем использовать функцию replicate :: Int -> a -> [a]
для повторения символа указанное количество раз. Например:
Prelude> replicate 3 'a'
"aaa"
Кроме того, функция digitToInt :: Char -> Int
может анализировать символ цифры на соответствующий Int
:
Prelude Data.Char> digitToInt '3'
3
Таким образом, здесь мы можем использовать эти два, чтобы каждый раз брать первые два символа строки и использовать replicate (digitToInt k) x
для генерации строки, где x
si повторяет запрошенное количество времени, и выполнять рекурсию для остальной части строка, как:
import Data.Char(digitToInt)
foo :: String -> String
foo (x:k:xs) = replicate (digitToInt k) x ++ foo xs
foo _ = ""