Тип const (++) в Haskell

Я пытаюсь понять тип выражения const (++) в Haskell. Я знаю отдельные типы const и (++), и я знаю, что вы можете не указывать параметры, чтобы вернуть частично примененные функции.

Если я наберу :t const (++), я получу const (++) :: b -> [a] -> [a] -> [a]. Я думаю, что (++) требуется два списка (однако я знаю, что все функции в Haskell - это каррированные функции, которые на самом деле принимают только один аргумент) и возвращает список. Этот список затем является первым аргументом функции const, которая ожидает еще одного аргумента. Итак, я подумал, что тип будет const (++) :: [a] -> [a] -> b -> [a].

Но, например: const (++) 1 "hello" "you" возвращает "helloyou". Почему то, что возвращается из операции const, не является первым аргументом, согласно определению const, которое равно const x _ = x? Где в моем мыслительном процессе я ошибаюсь?


person Nicrophorus    schedule 30.05.2017    source источник


Ответы (2)


Почему то, что возвращается из операции const, не является первым аргументом

Это. Первый аргумент const - (++). Таким образом, результат операции const (++) 1 на самом деле (++), что является первым аргументом. Итак, const (++) 1 это (++), то есть const (++) 1 "hello" "you" это (++) "hello" "you", а это "helloyou".

person sepp2k    schedule 30.05.2017
comment
и, const (++) 1 "hello" "you" то же самое, что (((const (++)) 1) "hello") "you" то же самое, что ((const (++) 1) "hello") "you" то же самое, что ( (++) "hello") "you" то же самое, (++) "hello" "you" то же самое, что "hello" ++ "you". - person Will Ness; 30.05.2017

(++) :: [a] -> [a] -> [a]
      ≡ ([a] -> [a] -> [a])

const :: c -> b -> c

Теперь в const (++) вы хотите передать (++) в качестве аргумента для const. Аргумент для const должен иметь тип c, поэтому вы объедините его с типом (++)

     c  ~  ([a] -> [a] -> [a])

и получите специализированную версию

const :: ([a] -> [a] -> [a]) -> b -> ([a] -> [a] -> [a])

Если это выглядит запутанным, рассмотрим более простой случай const 1. Если 1 имеет тип Int, тогда у нас должно быть c ~ Int и в этом случае

const :: Int -> b -> Int

Поскольку функциональные стрелки правоассоциативны, (++)-специализация также может быть записана

const :: ([a] -> [a] -> [a]) -> b -> [a] -> [a] -> [a]

Теперь, если вы действительно примените это к (++), вы насыщаете аргумент функции и в итоге получите

const (++) :: b -> [a] -> [a] -> [a]
person leftaroundabout    schedule 30.05.2017