Here is code illustrating the problem:
{-# LANGUAGE QuantifiedConstraints #-}
class SomeClass a b where
someFunction :: a -> b -> a
data FirstInInstanceOfSomeClass = forall a. (forall b. SomeClass a b) => First a
instance SomeClass Bool String where
someFunction = const
x = First True {-
• No instance for ‘SomeClass Bool b’
arising from the head of a quantified constraint
arising from a use of ‘First’
• In the expression: First True
In an equation for ‘x’: x = First Truetypecheck(-Wdeferred-
type-errors)
-}
I want x
to be a valid value since there is an instance of SomeClass
for Bool
, i.e., the one with String
. Is there a way to achieve this?
Clarification: there might be many instances of SomeClass
where Bool
is in the first position. What I want to require is that there shall be at least one such instance for Bool
so that FirstInInstanceOfSomeClass
may wrap Bool
values.
Edit: generally speaking, b
does not functionally depend on a
.
Your FirstInInstanceOfSomeClass
doesn't make sense: you want a
to be a parameter, not existential, and then b
should be existential, not universal (as in (exists b. SomeClass a b) => First a
, or equivalently forall b. SomeClass a b => First a
by currying, which is the syntax Haskell supports).
data FirstInInstanceOfSomeClass a = forall b. SomeClass a b => First a
Of course, the compiler now complains that b
is ambiguous in the type of First
; one way to fix that if you have a functional dependency of b
on a
is to just declare it:
{-# LANGUAGE FunctionalDependencies #-}
class SomeClass a b | a -> b where
someFunction :: a -> b -> a
Otherwise you can use AllowAmbiguousTypes
and TypeApplications
:
{-# LANGUAGE TypeApplications, AllowAmbiguousTypes #-}
data FirstInInstanceOfSomeClass a = forall b. SomeClass a b => First a
x = First @_ @String True
Or Proxy
:
import Data.Proxy
data FirstInInstanceOfSomeClass a = forall b. SomeClass a b => First (Proxy b) a
x = First (Proxy :: Proxy String) True