Shortest a -> b -> (a -> b) function in Haskell

19

3

I got the following question at a test:

Write a function f with the following type a -> b -> (a -> b). a and b should not be bound in any sense, the shorter the code, the better.

I came up with f a b = \x -> snd ([a,x],b). Can you find something tinier?

Currently the winner is: f _=(.f).const

Radu Stoenescu

Posted 2014-02-13T11:17:38.860

Reputation: 291

Can the answer be a partial function? – Post Rock Garf Hunter – 2018-06-10T15:14:38.753

If a more general type is allowed: f = const const. – hammar – 2014-02-13T12:22:02.247

@hammar: or f _ b _ = b, but, given the solution in the question, I suspect a more general type is not allowed. – Tikhon Jelvis – 2014-02-13T12:31:33.387

6If a more general type is allowed, why not f = id? – Tom Ellis – 2014-02-13T13:18:47.407

7In fact if a more general type is allowed then f = f is a solution, so I guess the conditions on the type are very important! – Tom Ellis – 2014-02-13T13:56:00.297

3A more general type is not allowed, your assumptions were correct. – Radu Stoenescu – 2014-02-14T09:28:11.090

If you're allowed to import Control.Applicative, you can replace const by pure, which is one character less. – bennofs – 2014-02-14T23:08:01.853

Answers

11

Your example can be shrunk by getting rid of the anonymous function on the right-hand side:

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

This works because the type a -> b -> a -> b is equivalent to a -> b -> (a -> b) in Haskell.

Matt Fenwick

Posted 2014-02-13T11:17:38.860

Reputation: 211

4Slightly shorter modification: f a b x = snd (f x,b) – Ed'ka – 2014-02-14T04:40:26.287

5

The function f _=(.f).const is actually of a more general type than f :: a -> b -> (a -> b), namely f :: a -> b -> (c -> b). If no type signature is given, the type inference system infers a type of f :: a -> b -> (a -> b), but if you include the type signature f :: a -> b -> (c -> b) with the exact same definition, Haskell will compile it without issue and will report consistent types for the partial applications of f. There is probably some deep reason why the type inference system is stricter than the type checking system in this case, but I don't understand enough category theory to come up with a reason as to why this should be the case. If you are unconvinced, you are welcome to try it yourself.

archaephyrryx

Posted 2014-02-13T11:17:38.860

Reputation: 1 035

might be like the case of f a b = f a a. it infers to be of type a -> a -> b although it complies with the type a -> b -> c. it is because if f is not given a type it can only use itself monomorphically. – proud haskeller – 2014-12-27T22:07:24.150

i don't think this should matter though – proud haskeller – 2014-12-27T22:07:45.833

4

Given ScopedTypeVariables, I came up with this:

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

If you shrink down both my function and yours, mine is a hair shorter:

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

Of course, you're probably not allowed to rely on ScopedTypeVariables :P.

Tikhon Jelvis

Posted 2014-02-13T11:17:38.860

Reputation: 141

3

This is not as short as f _=(.f).const (due to Sassa NF). Which also doesn't need ScopedTypeVariables.

– ceased to turn counterclockwis – 2014-02-13T12:07:51.737

Hmm, I initially thought this would require the first and third arguments to be lists... – Chris Taylor – 2014-02-13T12:29:34.957

@ChrisTaylor: Too much OCaml on the mind? :) – Tikhon Jelvis – 2014-02-13T12:30:20.117

Hah, must be! ;) – Chris Taylor – 2014-02-13T12:30:58.730