Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this type check?

Tags:

haskell

class Foo t where
  foo :: t

bar :: Binary t => t -> ()
bar = undefined

repro :: (Binary t, Foo t) => Proxy t -> ()
repro _proxy =
  bar (foo :: t)

The compiler complains:

  • Could not deduce (Binary t0) arising from a use of ‘bar’ from the context: (Binary t, Foo t) bound by the type signature for: repro :: forall t. (Binary t, Foo t) => Proxy t -> ()

  • Could not deduce (Foo t2) arising from a use of ‘foo’ from the context: (Binary t, Foo t) bound by the type signature for: repro :: forall t. (Binary t, Foo t) => Proxy t -> ()

Specifically, I am surprised it does not see I am passing t to bar, and creates a t0 type var. t2 is even more mysterious, because foo is explicitly annotated with type t.

like image 963
luntain Avatar asked Feb 17 '26 05:02

luntain


1 Answers

Type variables, by default, are not scoped that way. The t in the function signature and the t in the function body are not the same. Your code is equivalent to this:

repro :: (Binary t, Foo t) => Proxy t -> ()
repro _proxy =
  bar (foo :: a)

You need to enable the ScopedTypeVariables extension, and add an explicit forall t.

{-# LANGUAGE ScopedTypeVariables #-}

repro :: forall t. (Binary t, Foo t) => Proxy t -> ()
repro _proxy =
  bar (foo :: t)
like image 154
dcastro Avatar answered Feb 19 '26 11:02

dcastro



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!