Haskell 我正在寻找我的玩具语言评估器吗?
我正试图为我的玩具语言编写一个评估程序。我想包括的一件事是整数和双倍。以下是我的最新尝试:Haskell 我正在寻找我的玩具语言评估器吗?,haskell,Haskell,我正试图为我的玩具语言编写一个评估程序。我想包括的一件事是整数和双倍。以下是我的最新尝试: {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleInstances #-} module Types where import Prelude data family Number n data instance Number Integer = NumInt Integer deriving (Eq,
{-# 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
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
这是我的求值函数
{-# LANGUAGE GADTs #-}
module Eval where
import Types
eval :: Expr z -> z
eval (BoolConst b) = b
eval (NumConst b) = b
eval :: Expr z -> z
eval (BoolConst b) = b
eval (NumConst b) = b
eval (Equals a b) = (eval a) `equals` (eval b)
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
在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
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
现在,我尝试在eval函数中执行类似的操作
{-# LANGUAGE GADTs #-}
module Eval where
import Types
eval :: Expr z -> z
eval (BoolConst b) = b
eval (NumConst b) = b
eval :: Expr z -> z
eval (BoolConst b) = b
eval (NumConst b) = b
eval (Equals a b) = (eval a) `equals` (eval b)
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
然后,尝试编译:
~/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)
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
我认为我的思路是正确的,我只需要向ghc提供更多信息。我是,如果是,下一步是什么。如果没有,我该如何着手解决这个问题
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
Lazersmoke,你的建议奏效了,但我不得不给Equals构造函数添加一个约束。这是ghc的要求,但我不知道这是否仍然是一种不好的做法
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
GHC告诉您,它不可能知道每个
Number num
都有ChunkyNum
的实例。您可以通过将编号
数据族更改为ChunkyNum
的关联数据族来解决此问题:
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
class ChunkyNum a where
data Number a :: *
equals :: Number a -> Number a -> Bool
例如
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
instance ChunkyNum Integer where
data Number Integer = NumInt Integer
equals (NumInt a) (NumInt b) = a == b
否则,您将不得不编写一个实例ChunkyNum(Number num),其中
,这对于独立(开放)数据族是不可能的
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
如果这些不适用于您的用例,请告诉我
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
GHC告诉您,它不可能知道每个
Number num
都有ChunkyNum
的实例。您可以通过将编号
数据族更改为ChunkyNum
的关联数据族来解决此问题:
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
class ChunkyNum a where
data Number a :: *
equals :: Number a -> Number a -> Bool
例如
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
instance ChunkyNum Integer where
data Number Integer = NumInt Integer
equals (NumInt a) (NumInt b) = a == b
否则,您将不得不编写一个实例ChunkyNum(Number num),其中
,这对于独立(开放)数据族是不可能的
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
如果这些不适用于您的用例,请告诉我
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool
这是正确的。无论如何,您只能在
ChunkyNum
s上执行Equals
,因此该约束很有意义。如果你正在寻找设计改进,我会考虑你是否真的需要一个数据家族。您可以使用类型族,或者完全摆脱类型类,并对任何Eq
uatable或Num
ber进行操作。这是正确的。无论如何,您只能在ChunkyNum
s上执行Equals
,因此该约束很有意义。如果你正在寻找设计改进,我会考虑你是否真的需要一个数据家族。您可以使用一个类型族,或者完全摆脱类型类,对任何Eq
uatable或Num
ber进行操作。
Equals :: (ChunkyNum num) => Expr (Number num) -> Expr (Number num) -> Expr Bool