Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

explanation for "illegal type synonym family"

I'm just curious why I have to write this,

instance (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α, γ ~ ExprTyp 𝔪 α) => VarDecl 𝔪 γ where
    var = varhz

instead of this

instance (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α) => VarDecl 𝔪 (ExprTyp 𝔪 α) where
    var = varhz

-- error
Hz2/Language.hs:114:53:
    Illegal type synonym family application in instance: ExprTyp 𝔪 α
    In the instance declaration for `VarDecl 𝔪 (ExprTyp 𝔪 α)'

where

varhz ::
  (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α) =>
  String -> ExprTyp 𝔪 α -> 𝔪 (ExprTyp 𝔪 α)

What is the tilde anyway? Thanks very much.

like image 590
gatoatigrado Avatar asked Sep 23 '11 01:09

gatoatigrado


1 Answers

I think the problem is that everything on the right hand side of => must be either a type constructor or type variable. ExprTyp could refer to multiple differet type constructors. Replacing this with an equality constraint will indeed work, but the resulting instance will be effectively useless, since the compiler won't be able to deduce anything about γ given that it's an ExprTyp -- ExprTyp could be aliased to anything.

In my situation -- I'm trying to write a DSL monad -- the solution is to wrap all uses of the associated type in a newtype constructor. For example, if we start with,

class MyDSL m a where
    type ExprTyp m :: * -> *
    printE :: ExprTyp m a -> m ()

then wrapping this will result in

newtype ExprT a = ExprT a
class MyDSL m a where
    type ExprTyp m :: * -> *
    printE :: ExprT (ExprTyp m a) -> m ()

Then, for example, the variable declarations (I was writing code for tupled variable declarations) could be,

instance (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α, γ ~ ExprTyp 𝔪 α) => VarDecl 𝔪 (ExprT γ)
instance (Monad 𝔪, VarDecl 𝔪 α, VarDecl 𝔪 β) => VarDecl 𝔪 (α, β)

please post a comment if something is unclear.

like image 105
gatoatigrado Avatar answered Nov 07 '22 18:11

gatoatigrado