Определяя по приглашению GHCi
g = (\(n:arr) -> f n arr)
where
f = concatMap . replicate
, мы получаем производный тип как g :: [Int] -> [Int]
.Это определяет тип read
в map read
(подача в g
) как String -> Int
, и все работает.Может быть проще следовать в более читаемой форме:
g :: [Int] -> [Int]
g (n:arr) = concatMap (replicate n) arr
Тип Int
получен для n :: Int
из-за replicate :: Int -> a -> [a]
, а тип для arr
и (n:arr) :: [Int]
следует из этого, потому что списки Хаскелла однородны, то есть имеют все элементы одного типа.
Самый общий тип read
- read :: Read a => String -> a
.Действительно, Int
относится к классу Read
.
Но что, если мы не знаем, является ли это Int
, Double
или чем-то еще?Тогда read
не знает, какой формат анализировать, и поэтому мы получаем сообщение об ошибке "read: no parse"
.
Вот что происходит, когда мы пытаемся
(map read . words) "2\n3\n4\n" = map read $ words "2\n3\n4\n"
= map read (words "2\n3\n4\n")
$
появляется там вместо .
, когда мы открываем скобки.Из-за приоритета оператора ваша функция main
на самом деле
main :: IO ()
main = getContents >>=
(mapM_ print . (\(n:arr) -> f n arr) . map read . words)
= getContents >>= (\s ->
(mapM_ print . g . map read . words) s)
= getContents >>= (\s ->
mapM_ print $ g $ map read $ words s)
Использование .
вместо $
там, как вы это сделали, неправильно, потому что просто пропуск этих скобок неправильный, вызывает другое сообщение об ошибкеотносится к функциям, так как .
ожидает функцию в качестве аргумента справа, но ["2","3","4"]
не является функцией.