Ответ 1
Из-за карри. Подумайте о типе этого:
add 3 :: Integer -> Integer
Если вы даете add
одно число, оно возвращает функцию, которая сопоставляет Integer
с другим целым числом. Поэтому вы можете сделать это:
map (add 3) [1..10]
Не имеет смысла рассматривать аргументы по-разному от возвращаемых типов с частичным приложением.
ИЗМЕНИТЬ, чтобы уточнить
Я думаю, что bheklilr хорошо понимает, что подпись типа может быть прочитана следующим образом
add :: Integer -> (Integer -> Integer)
Мы можем взять функцию с большим количеством аргументов, zipWith3
, потому что это единственный, о котором я действительно могу думать.
zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
Если мы просто прочитаем, что для этого требуется функция, которая принимает 3 значения и возвращает четвертый, а затем 3 списка этих значений соответственно и возвращает список четвертого значения. Попробуйте это.
add3 :: Int -> Int -> Int -> Int
add3 a b c = a + b + c
Prelude>zipWith3 add3 [1] [2] [3]
[6]
Хотя в этом случае все значения имеют тип Int
, он все еще демонстрирует точку.
Теперь, если мы не дадим все списки? Что, если мы не дадим ему никаких списков, просто add3
.
zipWith3 add3 :: [Int] -> [Int] -> [Int] -> [Int]
zipWith3 add3 :: [Int] -> ([Int] -> [Int] -> [Int])
zipWith3 add3 :: [Int] -> [Int] -> ([Int] -> [Int])
Итак, теперь у нас есть функция, которая принимает 3 списка и возвращает список. Но это также функция, которая принимает список, возвращает функцию, которая принимает 2 списка и возвращает список. Нет никакого способа отличить их.
(zipWith3 add3) [1,2] [3,4] [5,6] :: [Int]
(zipWith3 add3) [1,2] :: [Int] -> [Int] -> [Int]
Посмотрите, где я собираюсь? Нет никакого различия между аргументами, являются возвращаемые типы.