Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function definition using type synonym is "less polymorphic than expected"

Given this type synonym:

type Synonym a b = (a, b)

this code doesn't work in GHCi:

ghci> let myFirst (f, s) = f :: Synonym a b -> a

<interactive>:1:21:
    Inferred type is less polymorphic than expected
      Quantified type variable `b' is mentioned in the environment:
        f :: Synonym a b -> a (bound at <interactive>:1:13)
      Quantified type variable `a' is mentioned in the environment:
        f :: Synonym a b -> a (bound at <interactive>:1:13)
    In the expression: f :: Synonym a b -> a
    In the definition of `myFirst':
        myFirst (f, s) = f :: Synonym a b -> a

but this does:

ghci> let myFirst = fst :: Synonym a b -> a
-- no problem --

This only happens when I type it directly into GHCi; both definitions work when I put them in files and :load them.

What is the problem here? I've run into this issue many times, but never understood why.

p.s. I tried :set -XNoMonomorphismRestriction, but that didn't make a difference.

like image 874
Matt Fenwick Avatar asked Jan 15 '23 19:01

Matt Fenwick


1 Answers

Haskell is trying to match the type signature to f, not to myFirst, and it doesn't work (I can't give more explanation than that though, someone else?). i.e. Haskell is treating it as:

let myFirst (f,s) = (f :: Synonym a b -> a)

You can fix this giving a separate signature

let myFirst :: Synonym a b -> a; myFirst (f,s) = f

or even using a lambda (this is essentially equivalent to the myFirst = fst definition)

let myFirst = (\(f,s) -> f) :: Synonym a b -> a

(Note that this fails even without the type synonym: let myFirst (f,s) = f :: (a,b) -> a doesn't work either.)

like image 133
huon Avatar answered Mar 01 '23 15:03

huon