Hi! So… I’m defining a small language that’s defined as follows:
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Test where
import Data.Kind (Type)
class RValue a b | a -> b where
rvalue :: a -> b
class Lift a b | a -> b where
inject :: a -> b
type EmbeddedValue m a = m (Value m a)
type EmbeddedLazy m a = m (Lazy m a)
class Exp m where
data Value m a :: Type
data Lazy m a :: Type
data Z' m :: Type
val :: Int -> m (Value m (Z' m))
defer :: (Lift a (m b))
=> a -> m (Lazy m b)
class Exp m => Act m where
data VariableData m a :: Type
halt :: m ()
show :: forall a b. (Show a, RValue b (m a)) => String -> b -> m ()
-- Please remember this!
class Declarable m b a | m b -> a where
declare :: b -> m a
type Constraints m =
( ExpConstraints m
, DeclarableConstraints m
, ActConstraints m
)
-- Type judgements, don't mind
type ExpConstraints m =
( Monad m
, Exp m
-- RValues
, m (Lazy m (Value m (Z' m))) `RValue` EmbeddedValue m (Z' m)
, forall a. m (Lazy m (Lazy m a)) `RValue` EmbeddedLazy m a
, EmbeddedValue m (Z' m) `RValue` EmbeddedValue m (Z' m)
, Value m (Z' m) `RValue` EmbeddedValue m (Z' m)
, Lazy m (Value m (Z' m)) `RValue` m (Value m (Z' m))
, forall a. Lazy m (Lazy m a) `RValue` EmbeddedLazy m a
-- Variable Data RValue Unfold
, VariableData m (m (Lazy m (Value m (Z' m)))) `RValue` EmbeddedValue m (Z' m)
, forall a. VariableData m (m (Lazy m (Lazy m a))) `RValue` EmbeddedLazy m a
, VariableData m (EmbeddedValue m (Z' m)) `RValue` EmbeddedValue m (Z' m)
, VariableData m (Value m (Z' m)) `RValue` EmbeddedValue m (Z' m)
, VariableData m (Lazy m (Value m (Z' m))) `RValue` m (Value m (Z' m))
-- Lift
, forall a. m (Value m a) `Lift` m (Value m a)
, forall a. Value m a `Lift` m (Value m a)
, forall a. Lazy m a `Lift` m (Lazy m a)
, forall a. m (Lazy m a) `Lift` m (Lazy m a)
-- Variable Data Lift Unfold
, forall a. VariableData m (Value m a) `Lift` m (Value m a)
, forall a. VariableData m (Lazy m a) `Lift` m (Lazy m a)
)
type DeclarableConstraints m =
( Monad m
, forall a. Declarable m (m (Value m a)) (VariableData m (Value m a))
, forall a. Declarable m (Value m a) (VariableData m (Value m a))
, forall a. Declarable m (VariableData m (Value m a)) (VariableData m (Value m a))
, forall a. Declarable m (m (Lazy m a)) (VariableData m (Lazy m a))
, forall a. Declarable m (Lazy m a) (VariableData m (Lazy m a))
, forall a. Declarable m (VariableData m (Lazy m a)) (VariableData m (Lazy m a))
)
type ActConstraints m =
( ExpConstraints m
, Act m
)
(The language is larger, but this subset will do). After defining everything, I wanted to try it outa very simple example:
example2 :: forall m. Constraints m => m ()
example2 = do
x <- declare u/m $ val @m 50
pure ()
Nevertheless, this fails to compile due to some ambiguous type var:
[1 of 1] Compiling Test ( src/Test.hs, interpreted )
src/Test.hs:93:10: error:
* Could not deduce (Declarable m (m (Value m (Z' m))) a0)
arising from a use of `declare'
from the context: Constraints m
bound by the type signature for:
example2 :: forall (m :: * -> *). Constraints m => m ()
at src/Test.hs:91:1-43
The type variable `a0' is ambiguous
Relevant bindings include
example2 :: m () (bound at src/Test.hs:92:1)
* In the first argument of `($)', namely `declare @m'
In a stmt of a 'do' block: x <- declare @m $ val @m 50
In the expression:
do x <- declare @m $ val @m 50
pure ()
|
93 | x <- declare @m $ val @m 50
| ^^^^^^^
Failed, no modules loaded.
I find it a bit unintuitive, since declare
only needs to know about the monad (given explicitly by the type annotation), and it’s argument (which is known, since if I add a type hole x <- declare @m $ (val @m 50 :: _)
, it infers a concrete type) in order to deduce the return type, which is the ambiguous a0
. Is this a bug in my GHC version (9.4.8)? Or Am I missing something on how type inference works with these extensions?