Haskell, проблемы с сопоставлением типов

#haskell #type-mismatch

#haskell #несоответствие типов

Вопрос:

Я не могу понять, почему функция:

 repli :: [a] -> Int -> [a]
repli xs n = concatMap (replicate n) xs
  

невозможно переписать как:

 repli :: [a] -> Int -> [a]
repli [] _ = []
repli (x:xs) n = (take n $ repeat x) : repli xs n
  

или

 repli :: [a] -> Int -> [a]
repli [] _ = []
repli (x:xs) n = (replicate n x) : repli xs n
  

Ghci жалуется:

 Couldn't match expected type ‘a’ with actual type ‘[a]’
  ‘a’ is a rigid type variable bound by
      the type signature for repli :: [a] -> Int -> [a]
      at 99questions.hs:41:10
Relevant bindings include
  xs :: [a] (bound at 99questions.hs:43:10)
  x :: a (bound at 99questions.hs:43:8)
  repli :: [a] -> Int -> [a] (bound at 99questions.hs:42:1)
In the first argument of ‘(:)’, namely ‘(replicate n x)’
In the expression: (replicate n x) : repli xs n
  

Я не понимаю, почему, поскольку при выполнении всех вычислений типа получается нормально. repeat x есть [a] и так take n есть [a] . Поэтому он не должен жаловаться.

Комментарии:

1. Я не совсем понимаю ваши намерения — почему вы передаете список в качестве аргумента? Похоже, вы пытаетесь воссоздать replicate то, что работает с отдельными элементами.

2. @shree.pat18: Да, это упражнение. Я просматриваю список 99 проблем Haskell.

Ответ №1:

Подпись (:) есть a -> [a] -> [a] . Поэтому у вас не может быть списков с обеих сторон оператора. Это причина вашей ошибки.

Вместо этого вы могли бы использовать ( ) , который имеет подпись [a] -> [a] -> [a] .

Комментарии:

1. И в первой функции (рабочей) была даже concat Map!