我试图为我的玩具语言编写评估员。我想要包括的一件事是Ints和Doubles。这是我最近的尝试:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
module Types where
import Prelude
data family Number n
data instance Number Integer = NumInt Integer deriving (Eq,Show)
-- data instance Number Double = NumDouble Double deriving (Eq,Show)
data Expr a where
BoolConst :: Bool -> Expr Bool
NumConst :: Number num -> Expr (Number num)
Equals :: Expr (Number num) -> Expr (Number num) -> Expr Bool
class ChunkyNum a where
equals :: a -> a -> Bool
-- more methods to be added
instance ChunkyNum (Number Integer) where
equals a b = a == b
这是我的评估功能
{-# LANGUAGE GADTs #-}
module Eval where
import Types
eval :: Expr z -> z
eval (BoolConst b) = b
eval (NumConst b) = b
在ghci,我可以做到这一点。
*Main Eval Types> let five = NumConst (NumInt 5 :: Number Integer)
*Main Eval Types> let ten = NumConst (NumInt 10 :: Number Integer)
*Main Eval Types> eval five == eval ten
False
现在,我尝试在我的eval函数中做类似的事情
eval :: Expr z -> z
eval (BoolConst b) = b
eval (NumConst b) = b
eval (Equals a b) = (eval a) `equals` (eval b)
然后,尝试编译:
~/projects/git/chunky/src/Eval.hs:12:26: error:
• Could not deduce (ChunkyNum (Number num))
arising from a use of ‘equals’
from the context: z ~ Bool
bound by a pattern with constructor:
Equals :: forall num.
Expr (Number num) -> Expr (Number num) -> Expr Bool,
in an equation for ‘eval’
at src/Eval.hs:12:7-16
• In the expression: (eval a) `equals` (eval b)
In an equation for ‘eval’:
eval (Equals a b) = (eval a) `equals` (eval b)
我认为我走在正确的轨道上,我只需要向ghc提供更多信息。我是,如果是的话,下一步是什么。如果没有,我该如何解决这个问题?
Lazersmoke,您的建议有效,但我必须向Equals构造函数添加约束。这是在ghc的要求下,但我想知道它是否仍然是不好的做法。
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
答案 0 :(得分:2)
GHC告诉您,它无法知道每个Number num
都会有ChunkyNum
的实例。您可以通过将Number
数据系列更改为ChunkyNum
的关联数据系列来解决此问题:
class ChunkyNum a where
data Number a :: *
equals :: Number a -> Number a -> Bool
使用像
这样的实例instance ChunkyNum Integer where
data Number Integer = NumInt Integer
equals (NumInt a) (NumInt b) = a == b
否则,您必须编写instance ChunkyNum (Number num) where
,这对于独立(开放)数据系列是不可能的。
如果这些内容不适用于您的使用案例,请与我们联系。