姬,那里!
我想創建一個包含元組的串列,這樣的元組由一個字串和第二個元素組成一個整數或布林值
我找到了這個答案: 具有不同型別的元組
但我認為這有點不同,因為我必須使用已經定義的資料,而不是使用 Int 或 Bool,問題是我不能將 Num(按 Int)或 B(按 Bool)放回去。
我的代碼
data EAB = Var String
| Num Int
| B Bool
| Sum EAB EAB
| Prod EAB EAB
| Neg EAB
| Pred EAB
| Suc EAB
| And EAB EAB
| Or EAB EAB
| Not EAB
| Iszero EAB
| If EAB EAB EAB
| Let EAB EAB
| Abs String EAB
-- Arithmetic and Boolean expression language
-- Example that I want
-- Ctx = [("x",Num),("y", B),("z", B),("w",Num)]
-- I tried
-- data Type = Num EAB | B EAB
-- type Ctx = [(String, Type)]
-- but doesn't work
這是因為我想定義一個函式,告訴我是否可以根據我的 EAB 對相等型別進行評估,例如
vt :: Ctx → EAB → Type → Bool
--- ...
-- Results
vt [] 4 5 Num = True
vt [] 4 False Num = False
vt [(x,Num)] 4 x Num = True
謝謝!
uj5u.com熱心網友回復:
只需使用新的建構式創建一個新型別。
data Type = NumT | BT
ctx = [("x", NumT), ("y", BT), ("z", BT), ("w", NumT)]
vt :: Ctx -> EAB -> Type -> Bool
vt [] (Sum (Num 4) (Num 5)) NumT = True -- etc.
uj5u.com熱心網友回復:
您無法制作您想要的串列,但即使您可以,您也無法制作您的vt功能。
您似乎打算使用您的型別的B和Num建構式來表示您的 EAB 語言中的型別。EAB那是不可能的。
建構式在 Haskell 中很特殊,因為您可以在模式匹配中使用它們。您可以撰寫一個模式,將建構式完全應用于其他模式,然后檢查它是否與模式型別的值匹配。像這樣:
case expr :: EAB
of Var s -> "Var: " <> s
Num n -> "Num: " <> show n
B b -> "B: " <> show b
在那個背景關系之外,建構式沒什么特別的。它們只是功能1。所以 yourNum是 type 的函式Int -> EAB,而 yourB是 type 的函式Bool -> EAB。你不能以任何方式比較函式。對函式唯一能做的就是應用它(應用于正確型別的引數),然后看看你得到了什么。
這意味著你的想象vt是不可能的。在第三個引數(你說它應該是Type你沒有定義的型別)中,你使用了Num. 但請記住,Num它只是 type 的一個函式Int -> EAB。函式實作無法vt查看它接收到的函式并測驗它是否是Num為了幫助決定回傳值是否應該是Trueor False。它唯一可能做的就是將其應用于 anInt然后檢查該EAB值。
但是您可能還希望能夠B在該位置傳遞,這樣就vt可以說明是否可以將給定EAB運算式評估為布林值。B是一個不同型別的函式Bool -> EAB。vt接受任一型別函式的第三個引數的唯一方法是使用型別變數對其進行泛化,使此引數為(a -> EAB)。但是沒有辦法vt知道這個函式可以應用于什么,所以它甚至不能做你可以用函式做的一件事!2
基本上Num,B不能用作您語言中型別的抽象表示。它們是EAB資料型別中的建構式,可幫助您以您的語言構建和檢查值。這就是他們的全部目的。正因為如此,沒有必要深入探討為什么你不能混合Num和B(里面的元組)串列3或者你如何能夠解決它。
Daniel Wagner 的建議只是停止嘗試EAB為此目的濫用建構式,而只需創建一個資料型別來表示您的語言中的型別!無論如何,這要好得多,因為EAB有 15 個建構式,但您的語言似乎只有兩種型別。4
所以你只需這樣做:
data EABType = NumT | BT
deriving (Eq, Show)
type Ctx = [(String, EABType)]
-- e.g. [("x",NumT),("y", BT),("z", BT),("w",NumT)
vt :: Ctx -> EAB -> EABType -> Bool
vt ctx expr ty
= case expr of
-- making some guesses about how you want vt to behave
Var s -> (s, ty) `elem` ctx
B _ -> ty == BT
Num _ -> ty == NumT
Sum l r -> ty == NumT && vt ctx l BT && vt ctx r BT
And l r -> ty == BT && vt ctx l BT && vt ctx r BT
...
1除非建構式沒有引數,否則它不是函式。除了模式匹配之外,您仍然無法比較它們(通過模式匹配Eq簡單地實作了一個實體)。但是空值建構式本身就是一個完整的模式,所以沒有什么是你無法比較的未應用空值建構式。
2假設我們可以對變數使用型別類約束,這樣就可以呼叫函式。例如,如果是(Monoid a => a -> EAB),那么我們總是可以用mempty. 但是,對于這個想法,您無法做任何事情來實際幫助您將這個引數用于您想要的目的,所以我不會在這個方向上更進一步。
3但是要強調一點:這和以前的原因是一樣的。B并且在您使用它們的背景關系中,它們只是具有不同型別的函式,您不能在串列中混合不同型別的函式,即使可以,一旦它們在串列中Num,您將無法對它們執行任何操作(例如查看串列中的每個元組并檢查其中的函式)。
4假設您要使用簡單的值型別,而不是嘗試將型別分配Bool -> Bool -> Bool給未應用的函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/462874.html
上一篇:創建一個IO字串
下一篇:Rn次相乘
