在GADT上使用折叠解释器

时间:2017-02-18 05:33:32

标签: haskell gadt

几周前,我读了Writing an interpreter using fold。我试图在我正在处理的项目上应用此方法,但由于GADT而出现错误。这是产生同样问题的玩具代码。

DECLARE @year INT = '2017', @month INT = '7'
SELECT CONVERT(VARCHAR(10),DATEFROMPARTS(@year, @month, 1), 103) AS [DD/MM/YYYY]

以下是错误消息。

DD/MM/YYYY
01/07/2017

我认为编译器无法推断{-# LANGUAGE GADTs, KindSignatures #-} data Expr :: * -> * where Val :: n -> Expr n Plus :: Expr n -> Expr n -> Expr n data Alg :: * -> * where Alg :: (n -> a) -> (a -> a -> a) -> Alg a fold :: Alg a -> Expr n -> a fold alg@(Alg val _) (Val n) = val n fold alg@(Alg _ plus) (Plus n1 n2) = plus (fold alg n1) (fold alg n2) /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:36: error: • Couldn't match expected type ‘n1’ with actual type ‘n’ ‘n’ is a rigid type variable bound by the type signature for: fold :: forall a n. Alg a -> Expr n -> a at /home/mossid/Code/Temforai/src/Temforai/Example.hs:15:9 ‘n1’ is a rigid type variable bound by a pattern with constructor: Alg :: forall a n. (n -> a) -> (a -> a -> a) -> Alg a, in an equation for ‘fold’ at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:11 • In the first argument of ‘val’, namely ‘n’ In the expression: val n In an equation for ‘fold’: fold alg@(Alg val _) (Val n) = val n • Relevant bindings include n :: n (bound at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:27) val :: n1 -> a (bound at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:15) fold :: Alg a -> Expr n -> a (bound at /home/mossid/Code/Temforai/src/Temforai/Example.hs:16:1) 是相同的类型,因此答案可能是将内部变量提升为数据类型的签名。但是,与此示例不同,它不能用于原始代码。原始代码在n中具有forall-quantified类型变量,类型签名必须处理特定信息。

+这是原始代码

n1

1 个答案:

答案 0 :(得分:2)

要确保n内的Alg是正确的,您可以将其作为参数公开给Alg类型的构造函数。

data Alg :: * -> * -> * where
    Alg :: (n ->      a) 
        -> (a -> a -> a) 
        -> Alg n a

fold :: Alg n a -> Expr n -> a
fold alg@(Alg val _) (Val n) = val n
fold alg@(Alg _ plus) (Plus n1 n2) = plus (fold alg n1) (fold alg n2)

Form代码中,这看起来更难。那里有很多存在量化的类型变量。我们需要找到一种方法来公开类型中的所有内容,以便在FormFormA中要求它们相同。