Benjamin Redelings benjamin.redelings at gmail.com
Wed Jan 19 22:34:41 UTC 2022

```1. Hmm... Perhaps ghc changes the code to

fgtuple:: (Eq a, Num a) => (Char -> a -> Char, Char -> Char -> Char)
fgtuple dEq dNum =
let f c i   = if i == 10 then c else g c 'b'
g 'a' w = f 'b' 10
g z   w = z
in (f,g)

f :: forall a. (Eq a, Num) => Char -> a -> Char
f dEq dNum = case fgtuple dEq dNum of (f,g) -> f

g :: Char -> Char -> Char
g = case fgtuple dEqInt dNumInt (f,g) -> g

In order words,

* the definition of fgtuple is not ambiguous.

* the defaulting is applied only to the definition of g, not the
definition of fgtuple.

Does that sound right?

2. Running ghc -ddump-tc shows:

{Exports: [f <= f_a2gf
wrap: <>,
g <= g_a2gi
wrap: <> @ Integer \$dEq_a2xJ \$dNum_a2xK]

The "wrap" code looks like the extra arguments that are applied by
defaulting.

-BenRI

On 1/19/22 11:19 AM, Benjamin Redelings wrote:

> Hi,
>
> I am trying to understand how GHC treats the following declaration.
>
> f c i   = if i == 10 then c else g c 'b'
> g 'a' w = f 'b' 10
> g z   w = z
>
> l = (f 'a' (1::Int), f 'a' (1.0::Double))
>
> It seems to me like, after defaulting, f should have the following type:
>
>      Char -> Int -> Char
>
> However, looking at -ddump-tc, GHC is deriving the polymorphic type
>
>      forall a. (Eq a, Num a) => Char -> a -> Char
>
> That's much nicer, because its more flexible.  But I'm confused,
> because it looks like GHC is defaulting 'g', but not 'f', even though
> they are in the same recursive group.  This seems to contradict
> "Typing Haskell in Haskell", which is what I am looking at right now.
> If that is correct, can anybody point me to a paper or documentation
>
> More detail:
>
> 1. If I understand correctly, the definitions of `f` and `g` are
> mutually recursive, and should be typed together, and the declaration
> group is not restricted.
>
> 2. It seems like, before generalization, we have
>
>      f :: Char -> a -> Char
>      g :: Char -> Char -> Char
>      Predicates include (Eq a, Num a)
>
> 3. Looking at the paper "Typing Haskell in Haskell" (THIH), it looks
> like the predicates (Num a, Eq a) should cause an ambiguity in the
> definition of g:
>
> * a is present in the definition of f, but not the definition of g
>
> * so the type (Eq a, Num a) => Char -> Char -> Char is ambiguous.
>
> * more generally, it seems like THIH treats any predicates with a type
> variable that is part of some, but not all, types in the declaration
> group to be ambiguous.  Does this sound right?
>
> 4. Then, again following THIH, this ambiguous predicate should be
> defaulted to Int.
>
> I THINK this should lead to
>
> 	f :: Char -> Int -> Char
> 	g :: Char -> Char -> Char
>
> 5. However, I'm still not sure I'm understanding this right, because a
> few things still don't make sense:
>
> * First, THIH seems to eliminate the defaulted predicates without
> substituting a -> Int.  But the type for f DOES mention `a`, so how
> can we avoid substituting?
>
> * Second, GHC accepts the code with no warnings or errors. There is
> some kind of defaulting going on, because GHC rejects the code if I
> add "default ()". Is there some way for GHC to default only g, but not f?
>
> I wonder if this involves a difference between Haskell '98 and Haskell
> 2010?
>
> I also wonder how much I should rely on THIH?  Maybe the language has
> moved on since then?
>
> -BenRI
>
-------------- next part --------------
An HTML attachment was scrubbed...
```