Кратчайшая функция a -> b -> (a -> b) в Haskell

19

На тесте я получил следующий вопрос:

Напишите функцию fследующего типа a -> b -> (a -> b). aи bне должно быть связано ни в каком смысле, чем короче код, тем лучше.

Я придумал f a b = \x -> snd ([a,x],b). Можете ли вы найти что-нибудь круче?

На данный момент победителем является: f _=(.f).const

Раду Стоенеску
источник
Если более общий тип допускается: f = const const.
хаммар
@hammar: или f _ b _ = b, но, учитывая решение вопроса, я подозреваю, что более общий тип не допускается.
Тихон Джелвис
6
Если разрешен более общий тип, почему бы и нет f = id?
Том Эллис
7
На самом деле, если разрешен более общий тип, тогда f = fэто решение, поэтому я думаю, что условия для типа очень важны!
Том Эллис
2
Более общий тип не допускается, ваши предположения были правильными.
Раду Стоенеску

Ответы:

11

Ваш пример можно сократить, избавившись от анонимной функции в правой части:

f a b x = snd ([a,x],b)

Это работает, потому что тип a -> b -> a -> bэквивалентен a -> b -> (a -> b)в Haskell.

Мэтт Фенвик
источник
4
Немного короче модификация:f a b x = snd (f x,b)
Ed'ka
5

Функция f _=(.f).constна самом деле имеет более общий тип, чем f :: a -> b -> (a -> b), а именно f :: a -> b -> (c -> b). Если сигнатура типа не указана, система вывода типов выводит тип f :: a -> b -> (a -> b), но если вы включите сигнатуру типа f :: a -> b -> (c -> b)с точно таким же определением, Haskell скомпилирует ее без проблем и сообщит согласованные типы для частичных применений f. Вероятно, есть какая-то глубокая причина, почему система вывода типов в этом случае строже, чем система проверки типов, но я не понимаю достаточно теории категорий, чтобы придумать причину, почему это должно быть именно так. Если вы не уверены, вы можете попробовать сами.

archaephyrryx
источник
может быть как в случае f a b = f a a. это означает, что он имеет тип, a -> a -> bхотя он соответствует типу a -> b -> c. это потому, что если fему не дан тип, он может использовать себя только мономорфно.
гордый haskeller
я не думаю, что это должно иметь значение, хотя
гордый haskeller
4

Учитывая ScopedTypeVariables, я придумал это:

f (_::a) b (_::a) = b

Если вы сократите и мою, и вашу функцию, у меня на голову короче:

f(_::a)b(_::a)=b
f a b x=snd([a,x],b)

Конечно, вы, вероятно, не можете положиться на ScopedTypeVariables: P.

Тихон Джелвис
источник
3
Это не так коротко, как f _=(.f).const( из-за Sassa NF ). Что тоже не нужно ScopedTypeVariables.
перестал поворачивать против часовой стрелки
Хм, я изначально думал, что это потребует, чтобы первый и третий аргументы были списками ...
Крис Тейлор
@ChrisTaylor: Слишком много OCaml на уме? :)
Тихон Джелвис
Ха, должно быть! ;)
Крис Тейлор