我有以下Haskell代码(只是所有代码的一个片段,但可以工作):
data ByteCode t where
INT :: Int -> ByteCode Int
BOOL:: Bool -> ByteCode Bool
Add :: ByteCode Int -> ByteCode Int -> ByteCode Int
Mul :: ByteCode Int -> ByteCode Int -> ByteCode Int
newtype C t = C (Int -> (ByteCode t, Int))
unC (C t) = t
instance Symantics C where
int x = C(\vc -> (INT x, vc))
bool b = C(\vc -> (BOOL b, vc))
add e1 e2 = C(\vc -> let (e1b,vc1) = unC e1 vc
(e2b,vc2) = unC e2 vc1
in (Add e1b e2b,vc2))
mul e1 e2 = C(\vc -> let (e1b,vc1) = unC e1 vc
(e2b,vc2) = unC e2 vc1
in (Mul e1b e2b,vc2))我正在尝试把它转换成模板Haskell。具体来说,我想摆脱ByteCode,只使用ExpQ (对我来说是新的)模板Haskell类型。所以现在我有:
newtype C a = C ExpQ
unC (C x) = x我正在尝试更新实例,所以我的新代码是:
newtype C t = C ExpQ
unC (C t) = t
instance Symantics C where
int x = C(\vc -> (ExpQ x, vc))
bool b = C(\vc -> (ExpQ b, vc))
add e1 e2 = C(\vc -> let (e1b,vc1) = unC e1 vc
(e2b,vc2) = unC e2 vc1
in (Add e1b e2b,vc2))但我得到了许多无法匹配的预期类型‘Q’与实际类型‘t1 -> (t0,t1)’错误。如何才能最好地编写这个新实例?
发布于 2020-11-27 17:10:57
在原始的C类型中,有一个整数"state“贯穿于计算过程中,这意味着C newtype实际上包装了一个类型为函数的:
Int -> (ByteCode t, Int)这些表述如下:
C (\vc -> ...) -- C constructor takes a function和
unC e1 vc -- unC e1 gets the function, and it's applied to vc在原始代码中反映了这一点。
在新的C类型中,您已经删除了状态,C新类型只是一个ExpQ,但是您没有更新任何代码来反映这种更改,因此在ExpQ (由新C包装的类型)和表单Int -> (ByteCode t, Int)的函数(由旧C包装的类型)之间存在类型不匹配错误。
你可能会更接近你的预期目标,比如:
instance Symantics C where
int x = C $ litE (IntegerL (fromIntegral x))
bool False = C [|False|]
bool True = C [|True|]
add e1 e2 = C [|$(unC e1) + $(unC e2)|]https://stackoverflow.com/questions/65029687
复制相似问题