【发布时间】:2019-01-22 18:26:25
【问题描述】:
我想使用类型级编程混合已评估和未评估的术语。
我做了一个简单的例子,其中 Sum 不求值,而 Const 求值。
以下工作正常:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
module Main where
type family And a b where
And 'True 'True = 'True
And _ _ = 'False
data TermList (b::Bool) where
Nil :: TermList 'True
Cons :: Term a -> TermList b -> TermList (And a b)
instance Show (TermList b) where
show Nil = "Nil"
show (Cons a b) = "(Cons " ++ show a ++ " " ++ show b ++ ")"
data Term (b::Bool) where
Const :: Int -> Term 'True
Sum :: TermList v -> Term 'False
instance Show (Term b) where
show (Const a) = "(Const " ++ show a ++ ")"
show (Sum a) = "(Sum " ++ show a ++ ")"
class Eval e where
eval :: e -> Term 'True
instance Eval (Term 'True) where
eval = id
instance Eval (Term 'False) where
eval (Sum x) = eval x
instance Eval (TermList b) where
eval _ = Const 0
{-
instance Eval (TermList b) where
eval (Nil) = Const 0
eval (Cons x xs) = case (eval x, eval xs) of
(Const v, Const vs) -> Const (v + vs)
-}
main :: IO ()
main =
let sum1 = Sum (Cons (Const 3) (Cons (Const 4) Nil))
sum2 = Sum (Cons (Const 5) (Cons (Const 6) Nil))
sum3 = Sum (Cons sum1 (Cons sum2 Nil))
in
do
putStrLn (show sum1)
putStrLn (show sum2)
putStrLn (show sum3)
putStrLn (show (eval sum1))
putStrLn (show (eval sum2))
putStrLn (show (eval sum3))
但是,将 TermList 的评估替换为 cmets 中的评估:
src\Main.hs:45:30: error:
* Could not deduce (Eval (Term a)) arising from a use of `eval'
from the context: b ~ And a b1
bound by a pattern with constructor:
Cons :: forall (a :: Bool) (b :: Bool).
Term a -> TermList b -> TermList (And a b),
in an equation for `eval'
at src\Main.hs:45:11-19
* In the expression: eval x
In the expression: (eval x, eval xs)
In the expression:
case (eval x, eval xs) of { (Const v, Const vs) -> Const (v + vs) }
|
45 | eval (Cons x xs) = case (eval x, eval xs) of
| ^^^^^^
这真的让我很惊讶:必须记住所有组成部分的类型吗?
【问题讨论】:
-
eval除了计算结果为Term 'True的函数外,永远无法返回任何内容。在您的模式匹配中,如果x是TermList v会发生什么?我认为你得到了一个矛盾,阻止 GHC 推断类型。 -
我可以看到问题所在,但不知道如何解决。要在
x上使用eval,它的类型是Term a(布尔值a是existential-ish)需要Eval (Term a)的实例在范围内。但我们只有Eval (Term 'True)和Eval (Term 'False)在范围内。
标签: haskell type-level-computation