La función más corta a -> b -> (a -> b) en Haskell

19

Recibí la siguiente pregunta en una prueba:

Escribe una función fcon el siguiente tipo a -> b -> (a -> b). ay bno debe estar vinculado en ningún sentido, cuanto más corto sea el código, mejor.

Se me ocurrió f a b = \x -> snd ([a,x],b). ¿Puedes encontrar algo más pequeño?

Actualmente el ganador es: f _=(.f).const

Radu Stoenescu
fuente
Si se permite que un tipo más general: f = const const.
hammar
@hammar: o f _ b _ = b, pero, dada la solución en la pregunta, sospecho que no se permite un tipo más general .
Tikhon Jelvis
66
Si se permite un tipo más general, ¿por qué no f = id?
Tom Ellis
77
De hecho, si se permite un tipo más general, entonces f = fes una solución, ¡así que supongo que las condiciones en el tipo son muy importantes!
Tom Ellis
2
No se permite un tipo más general, sus suposiciones eran correctas.
Radu Stoenescu

Respuestas:

11

Su ejemplo puede reducirse al deshacerse de la función anónima en el lado derecho:

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

Esto funciona porque el tipo a -> b -> a -> bes equivalente a a -> b -> (a -> b)en Haskell.

Matt Fenwick
fuente
44
Modificación ligeramente más corta:f a b x = snd (f x,b)
Ed'ka
5

La función f _=(.f).constes en realidad de un tipo más general que f :: a -> b -> (a -> b), a saber f :: a -> b -> (c -> b). Si no se proporciona una firma de tipo, el sistema de inferencia de tipo infiere un tipo de f :: a -> b -> (a -> b), pero si incluye la firma de tipo f :: a -> b -> (c -> b)con la misma definición exacta, Haskell la compilará sin problemas e informará tipos consistentes para las aplicaciones parciales de f. Probablemente haya alguna razón profunda por la cual el sistema de inferencia de tipo es más estricto que el sistema de verificación de tipo en este caso, pero no entiendo suficiente teoría de categoría para llegar a una razón de por qué este debería ser el caso. Si no está convencido, puede probarlo usted mismo.

Archaephyrryx
fuente
podría ser como el caso de f a b = f a a. se infiere que es de tipo a -> a -> baunque cumple con el tipo a -> b -> c. es porque si fno se le da un tipo, solo puede usarse monomórficamente.
orgulloso Haskeller
Sin embargo
orgulloso Haskeller
4

Dado ScopedTypeVariables, se me ocurrió esto:

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

Si reduce tanto mi función como la suya, la mía es un cabello más corto:

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

Por supuesto, probablemente no se le permita confiar en ScopedTypeVariables: P.

Tikhon Jelvis
fuente
3
Esto no es tan corto como f _=(.f).const( debido a Sassa NF ). Lo que tampoco necesita ScopedTypeVariables.
dejó de girar en sentido contrario a las agujas del reloj
Hmm, inicialmente pensé que esto requeriría que el primer y el tercer argumento fueran listas ...
Chris Taylor
@ ChrisTaylor: ¿Demasiado OCaml en la mente? :)
Tikhon Jelvis
Ja, debe ser! ;)
Chris Taylor