Reputation: 614
I want to put my typed GADT (GExpr) into a hashmap, so I first convert it to a corresponding monomorphic ADT (Expr). When I lookup from the hashmap I'm having trouble converting the monomorphic ADT back into a GADT.
The following is a simplified version. Essentially there are two functions, "dim" and "gexprOfExpr" and I can only get one of them to work at once. Is what I'm trying to do impossible?
{-# OPTIONS_GHC -Wall #-}
{-# Language GADTs #-}
type ListDim = [Int]
data DIM0 = DIM0
data DIM1 = DIM1
class Shape sh where
shapeOfList :: ListDim -> sh
instance Shape DIM0 where
shapeOfList _ = DIM0
instance Shape DIM1 where
shapeOfList _ = DIM1
data Expr = EConst ListDim Double
| ESum ListDim Int
data GExpr sh where
GRef :: sh -> Int -> GExpr sh
GConst :: sh -> Double -> GExpr sh
GSum :: GExpr DIM1 -> GExpr DIM0 -- GADT, this works for "dim"
-- GSum :: GExpr DIM1 -> GExpr sh -- phantom type, this works for "gexprOfExpr"
dim :: GExpr sh -> sh
dim (GRef sh _) = sh
dim (GConst sh _) = sh
dim (GSum _) = DIM0
gexprOfExpr :: Shape sh => Expr -> GExpr sh
gexprOfExpr (EConst lsh x) = GConst (shapeOfList lsh) x
gexprOfExpr (ESum lsh k) = GSum $ GRef (shapeOfList lsh) k
Note: I do know the type I'm trying to recover. If it would help, this would be fine:
gexprOfExpr :: Shape sh => sh -> Expr -> GExpr sh
Upvotes: 4
Views: 205
Reputation: 614
Saizan from #haskell gave me a tip that led to an answer. Here's the working version:
{-# OPTIONS_GHC -Wall #-}
{-# Language GADTs #-}
import Data.Maybe
type ListDim = [Int]
data DIM0 = DIM0
data DIM1 = DIM1
class Shape sh where
shapeOfList :: ListDim -> sh
maybeGExprOfExpr :: Expr -> Maybe (GExpr sh)
maybeGExprOfExpr _ = Nothing
instance Shape DIM0 where
shapeOfList _ = DIM0
maybeGExprOfExpr (ESum lsh k) = Just $ GSum $ GRef (shapeOfList lsh) k
maybeGExprOfExpr _ = Nothing
instance Shape DIM1 where
shapeOfList _ = DIM1
data Expr = EConst ListDim Double
| ESum ListDim Int
data GExpr sh where
GRef :: sh -> Int -> GExpr sh
GConst :: sh -> Double -> GExpr sh
GSum :: GExpr DIM1 -> GExpr DIM0
dim :: GExpr sh -> sh
dim (GRef sh _) = sh
dim (GConst sh _) = sh
dim (GSum _) = DIM0
gexprOfExpr :: Shape sh => Expr -> GExpr sh
gexprOfExpr (EConst lsh x) = GConst (shapeOfList lsh) x
gexprOfExpr e@(ESum _ _) = fromJust $ maybeGExprOfExpr e
Upvotes: 3