将 Haskell 转换为模板 Haskell: 无法匹配预期类型 ExpQ

Converting Haskell to Template Haskell: couldn't match expected type ExpQ

我有以下 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))

但是我收到了很多 Couldn't match expected type 'Q Exp' with actual type 't1 -> (t0, t1)' 错误。我怎样才能最好地编写这个新实例?

在原始的 C 类型中,有一个整数“state”贯穿计算,这意味着 C 新类型实际上包装了一个 function类型:

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) 形式的函数(由旧 [=14 包装的类型)之间出现类型不匹配错误=]).

您可能会通过以下方式更接近您的预期目标:

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)|]