haskell - не удалось сопоставить тип ‘(Char, Int)’ с ошибкой ‘[Char]’ - PullRequest
0 голосов
/ 30 октября 2018

Я пишу функцию для расширения строки

Пример:

foo "a4b4"

должен вернуть:

"aaaabbbb"

Вот мой код:

foo :: String -> String
foo (x:xs) = let curent = fooHelp(x, read $ charToString( xs !! 0  ) :: Int)
             in x : (curent) ++ foo (tail xs)

fooHelp:

fooHelp :: String -> Int -> String
fooHelp x n 
             | n >= 3 = x ++ fooHelp x (n - 1) 
             | n == 2 = x
             | n == 1 = ""

и charToString:

charToString :: Char -> String
charToString c = [c]

он берет х и добавляет его к текущему. В текущем fooHelp вернет расширенную строку

пример: foo "a4b4" затем x = "a", xs = "4b4", xs !! 0 = '4' read $ charToString( xs !! 0 ) :: Int) преобразует char '4' в int 4 и передает его в fooHelp вместе с x ("a") -> fooHelp(x, 4) и возвращает "aaa". Затем x : current должен вернуть "aaaa", потому что x = "a" и текущий "aaa", а затем рекурсивный вызов с ++ foo tail xs, где xs ="b4", и он должен повторить процесс.

Я получаю ошибку:

test.hs:173:34: error:
    • Couldn't match type ‘(Char, Int)’ with ‘[Char]’
      Expected type: String
        Actual type: (Char, Int)
    • In the first argument of ‘fooHelp’, namely
        ‘(x, read $ charToString (xs !! 0) :: Int)’
      In the expression:
        fooHelp (x, read $ charToString (xs !! 0) :: Int)
      In an equation for ‘curent’:
          curent = fooHelp (x, read $ charToString (xs !! 0) :: Int)
    |
173 | foo (x:xs) = let curent = fooHelp(x, read $ charToString( xs !! 0  ) :: Int)
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Где я ошибся? Я протестировал функцию fooHelp, и она отлично работает с такими аргументами, как в foo.

Тестирование fooHelp:

xs = "4b4"

test =  read $ charToString( xs !!0 ) :: Int

*Main> test
4

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Классическая ошибка - вызывать такую ​​функцию, как 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 _ = ""
0 голосов
/ 30 октября 2018

Выражение fooHelp(x, read $ charToString( xs !! 0 ) :: Int) пытается передать один аргумент - пару (Char, Int) - fooHelp, что неверно. Предположительно, вместо этого вы хотите написать:

fooHelp (charToString x) (read $ charToString( xs !! 0  ) :: Int)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...