I’ve been trying to build tagged AST for a while now. Let’s introduce the issue:
data E a
= V a
| LitInt Int
| LitBool Bool
| FooIntBool (E a) (E a) -- er…
deriving (Eq,Show)
The issue with that piece of code, to me, resides in FooIntBool
. The idea is that it takes an int expression and a bool expression, and glues them together. But E a
could be anything. This would be valid given the above definition of E
:
FooIntBool (LitInt 3) (LitInt 0)
You can see the issue. Then, what do we want? A tagged expression. This is not possible given the current definition of E, so let’s introduce some GADTs:
data E :: * -> * -> * where
V :: a -> E l a
LitInt :: Int -> E Int a
LitBool :: Bool -> E Bool a
FooIntBool :: E Int a -> E Bool a -> E (Int,Bool) a
This is quite nice! I can now right that kind of code:
FooIntBool (V "x") (LitBool False)
The issue with that is when I want to make it a monad, or an applicative. It’s just impossible. Consider the monad implementation:
instance Monad (E l) where
return = V
That was obvious and straight-forward. Let’s see the bind implementation:
V x >>= f = f x -- obvious as well
LitInt a >>= _ = LitInt a -- obvious yeah
LitBool a >>= _ = LitBool a -- …
FooIntBool a b >>= f = FooIntBool (a >>= ?) (b >>= ?) -- AH?
We can’t write a >>= f
and b >>= f
since f :: a -> E l b
. I haven’t found a solution to that issue yet, and I’m really curious how to deal with that and still being able to use de Bruijn indices (through bound).
Int
and aBool
. – ElateriteV
, it seems to be the variable name type, but this type is lost in the definition ofFooIntBool
in the specific case of your example. – KassandraFooIntBool :: Int -> Bool -> E (Int,Bool) a
, but of course it doesn’t work if I want to fetch theInt
orBool
from aV
. – ElateriteInt
,Bool
, and pairs of these, and it would be perfectly fine for some applications. Sorry if I sounded harsh, I merely wanted to know what is your intent. Besides, @JAbrahamson is right when he speaks about simpler methods: do it step by step. – Kassandraa
inE x a
seems to indicate that allV
subterms are labeled with a value of typea
, which strikes me as a strange invariant to care about. I would expect just one type argument, and for thea
inE a
to indicate that you can evaluate the expression to produce a value of typea
. – LearntE
to expose the type of index used for variables. Quite interesting! – Kassandraa
is a name. – Elaterite