1

This question is based on an exercise question in the book "Haskell Programming from first principles". It's for helping us understand parametricity.

How do we get type signature a -> a -> a? The book states that there are only 2 type signatures that work.

I've tried these, but they all failed:

test1 a a = a ERROR - Repeated variable "a" in pattern

test1 = \ a -> a -> a ERROR - Syntax error in input (unexpected `->')

test1 _ a = id a wrong result: test1 :: a -> b -> b

test1 a = id a . id a wrong result: test1 :: (a -> a) -> a -> a

test1 a b = a + b wrong result due to the Num type constructor: test1 :: Num a => a -> a -> a

maxloo
  • 453
  • 2
  • 12
  • One note about `test1 a a = a`. You are naming both arguments `a`. One could interpret it as saying "this is a partial function that, when the two arguments are *exactly* the same, it returns the argument, otherwise gives an error". In Haskell those kinds of patterns are forbidden *at the term level*. They are allowed at the type level though, in function-like "type families" that transform types into other types (instead of terms into other terms) https://stackoverflow.com/questions/35891663/what-are-nonlinear-patterns They are called "non-linear patterns". – danidiaz Jul 17 '20 at 06:41
  • 2
    ``foo1 x y = (y `asTypeOf` x) `seq` x`` ; ``foo2 x y = (y `asTypeOf` x) `seq` y`` . `foo3 x y = [x,y] !! 0` ; `foo4 x y = [x,y] !! 1` . – Will Ness Jul 17 '20 at 16:57
  • I would advise you to get more thoroughly familiar with Haskell syntax and wiring Haskell functions before tackling parametricity exercises. – dfeuer Jul 17 '20 at 23:10
  • @WillNess: Thanks, all 4 of your solutions worked! – maxloo Jul 26 '20 at 11:31

1 Answers1

4

Since you don't know anything about the type a, the only two functions that can have type signature a -> a -> a are:

someFunc  a b = a

-- and

someFunc2 a b = b

Being unable to operate on the values, the only valid returns are either the first argument or the second one.


As an interesting note, you can write this without referencing b at all.

someFunc    = const
someFunc2 _ = id
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • As an aside, HPFFP is an excellent read and I've strongly recommended it to a number of colleagues. Great purchase :) – Adam Smith Jul 17 '20 at 06:32
  • @Adam: I tried what you suggested and got this in return from my installation of HUGS: `someFunc :: a -> b -> a`. Could HUGS be unsuitable for testing type signatures? – maxloo Jul 17 '20 at 06:43
  • 4
    @maxloo: ... but there are only two functions that can be defined with type signature `a -> a -> a`, that is, after a declaration `f :: a-> a -> a` there are just two functions `f` that can possibly be defined. Both have a more general type as well. Functions usually have many types, but there can be only one _most general_ type. – Hans Lub Jul 17 '20 at 06:54
  • @HansLub: Thanks, I think I get it. I tried to force the type signature with a `someFunc :: a -> a -> a` along with `someFunc a b = a` and it worked. :) – maxloo Jul 17 '20 at 07:08
  • 1
    @AdamSmith `someFunc = const` – user253751 Jul 17 '20 at 10:30