我正在學習 Haskell 并試圖轉錄一本書中的語法和一些隨后的評估規則(TAPL,Pierce:https ://theswissbay.ch/pdf/Gentoomen Library/Maths/Comp Sci Math/Benjamin_C 。 _Pierce-Types_and_Programming_Languages-The_MIT_Press(2002).pdf)在第 48 頁(也在第 44 頁,但我將它們混合),但我遇到了一些麻煩。正如您在 pg 上看到的那樣。48(和 44),語法nv是一個子集,v而且它們在語意中穿插使用,這就是我試圖用下面的代碼來完成的:
data Expr = Tr | Fl | IfThenElse Expr Expr Expr | IsZero Expr | Succ Expr | Pred Expr |Zero
deriving (Show, Eq)
data V = NV
deriving (Show, Eq)
data NV = Zero | Succ NV
deriving (Show, Eq)
ssos :: Expr -> Expr
-- PAGE 44
-- E-IFTRUE
ssos (IfThenElse Tr t2 t3) = t2
-- E-IFFALSE
ssos (IfThenElse Fl t2 t3) = t3
-- E-IF
ssos (IfThenElse t1 t2 t3) = let t' = ssos t1 in IfThenElse t' t2 t3
-- PAGE 48
-- E-SUCC
ssos (Succ t1) = let t' = ssos t1 in Succ t'
-- E-PREDZERO
ssos (Pred Zero) = Zero
-- E-PREDSUCC
ssos (Pred (Succ nv1)) = nv1
-- E-PRED
ssos (Pred t1) = let t' = ssos t1 in Pred t'
-- E-ISZEROZERO
ssos (IsZero Zero) = Tr
-- E-ISZEROSUCC
ssos (IsZero (Succ nv1)) = Fl
-- E-ISZERO
ssos (IsZero t1) = let t' = ssos t1 in IsZero t'
而錯誤是“多次宣告”的錯誤,因為我既定義這是有道理的Succ,并Zero在兩個不同的型別,但是當我更改名稱之類的減免一切。
有沒有辦法可以制作Succ一種型別Expr但也可以NV像書中顯示的型別一樣?
謝謝!
uj5u.com熱心網友回復:
一種可能性是撰寫一個可以充當Expr或的單一泛型型別NV,具體取決于您如何對其進行引數化:
{-# LANGUAGE DataKinds, KindSignatures, GADTs, StandaloneDeriving #-}
import Data.Kind (Type)
data ExprFlavour = IsExpr | IsNV
type Expr = GenericExpr 'IsExpr
type NV = GenericExpr 'IsNV
data GenericExpr :: ExprFlavour -> Type where
Tr :: Expr
F1 :: Expr
IfThenElse :: Expr -> Expr -> Expr
IsZero :: Expr -> Expr
Succ :: GenericExpr flv -> GenericExpr flv
Pred :: Expr -> Expr
Zero :: GenericExpr flv
deriving instance Show (GenericExpr flv)
*Main> Succ Zero :: NV
Succ Zero
*Main> Succ Zero :: Expr
Succ Zero
*Main> Succ Tr :: Expr
Succ Tr
*Main> Succ Tr :: NV
:7:1: error:
? Couldn't match type ‘'IsExpr’ with ‘'IsNV’
Expected type: NV
Actual type: GenericExpr 'IsExpr
? In the expression: Succ Tr :: NV
In an equation for ‘it’: it = Succ Tr :: NV
uj5u.com熱心網友回復:
Haskell 中最好的方法是真正以不同的方式重命名建構式。然后您會收到錯誤訊息,準確地告訴您需要修復哪些名稱。
uj5u.com熱心網友回復:
我認為 leftaroundabout 的現有答案可能比那本書的意圖要復雜一些/對初學者來說很有意義。與其嘗試為值使用單獨的型別,另一種選擇是簡單地使用謂詞:
isValue :: Expr -> Bool
實作如下:
isValue Tr = True -- from page 44
isValue Fl = True
isValue Zero = True -- from page 48
isValue (Succ e) = isValue e
isValue _ = False
畢竟,值與運算式并沒有什么不同。它們是運算式,只是幾種特定形狀之一。
您的Expr型別并不需要改變,V而NV消失的物體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/316845.html
標籤:哈斯克尔
上一篇:在Haskell中,[0.1..1]回傳[0.1,1.1]。為什么?[復制]
下一篇:Haskell模式匹配布林值
