Função a -> b -> (a -> b) mais curta em Haskell

19

Eu recebi a seguinte pergunta em um teste:

Escreva uma função fcom o seguinte tipo a -> b -> (a -> b). ae bnão deve ser vinculado em nenhum sentido, quanto menor o código, melhor.

Eu inventei f a b = \x -> snd ([a,x],b). Você consegue encontrar algo menor?

Atualmente o vencedor é: f _=(.f).const

Radu Stoenescu
fonte
Se um tipo mais geral é permitido: f = const const.
Hammar
@hammar: ou f _ b _ = b, mas, dada a solução na pergunta, suspeito que um tipo mais geral não seja permitido.
Tikhon Jelvis
6
Se um tipo mais geral é permitido, por que não f = id?
Tom Ellis
7
De fato, se um tipo mais geral é permitido, então f = fé uma solução, então acho que as condições no tipo são muito importantes!
Tom Ellis
2
Um tipo mais geral não é permitido, suas suposições estavam corretas.
Radu Stoenescu

Respostas:

11

Seu exemplo pode ser reduzido ao se livrar da função anônima no lado direito:

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

Isso funciona porque o tipo a -> b -> a -> bé equivalente a -> b -> (a -> b)em Haskell.

Matt Fenwick
fonte
4
Modificação ligeiramente mais curta:f a b x = snd (f x,b)
Ed'ka 14/02/14
5

A função f _=(.f).consté realmente de um tipo mais geral que f :: a -> b -> (a -> b), a saber f :: a -> b -> (c -> b). Se nenhuma assinatura de tipo for fornecida, o sistema de inferência de tipo inferirá um tipo de f :: a -> b -> (a -> b), mas se você incluir a assinatura de tipo f :: a -> b -> (c -> b)com exatamente a mesma definição, Haskell a compilará sem problemas e relatará tipos consistentes para as aplicações parciais de f. Provavelmente, existe alguma razão profunda pela qual o sistema de inferência de tipo é mais rigoroso do que o sistema de verificação de tipo neste caso, mas não entendo a teoria de categorias suficiente para apresentar uma razão de por que esse deveria ser o caso. Se você não está convencido, pode tentar por conta própria.

archaephyrryx
fonte
pode ser como o caso de f a b = f a a. infere ser do tipo, a -> a -> bembora esteja em conformidade com o tipo a -> b -> c. é porque, se fnão receber um tipo, ele só poderá usar-se monomorficamente.
proud haskeller
eu não acho que isso deve importa embora
haskeller orgulhoso
4

Dado ScopedTypeVariables, eu vim com isso:

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

Se você reduzir minha função e a sua, a minha é mais curta:

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

Claro, você provavelmente não tem permissão para confiar em ScopedTypeVariables: P.

Tikhon Jelvis
fonte
3
Isso não é tão curto quanto f _=(.f).const( devido ao Sassa NF ). O que também não precisa ScopedTypeVariables.
deixou de girar no sentido anti-horáriowis
Hmm, eu inicialmente pensei que isso iria exigir que os primeiro e terceiro argumentos para ser listas ...
Chris Taylor
@ ChrisTaylor: Muito OCaml na mente? :)
Tikhon Jelvis
Hah, deve ser! ;)
Chris Taylor