[英]Lists of different tuples in haskell
姬,那里!
我想制作一個包含元組的列表,這樣的元組由一個字符串和第二個元素組成 integer 或 boolean
我找到了這個答案: 不同類型的元組
但我認為它有點不同,因為我必須使用我已經定義的數據,而不是使用 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
這是因為我想定義一個 function 來告訴我是否可以根據我的 EAB 對相同類型進行評估,例如
vt :: Ctx → EAB → Type → Bool
--- ...
-- Results
vt [] 4+5 Num = True
vt [] 4+False Num = False
vt [(x,Num)] 4+x Num = True
謝謝!
只需使用新的構造函數創建一個新的類型。
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.
你不能列出你想要的列表,但即使你可以,你也不能列出你的vt
function。
您似乎打算使用EAB
類型的B
和Num
構造函數來表示 EAB 語言中的類型。 那是不可能的。
構造函數在 Haskell 中是特殊的,因為您可以在模式匹配中使用它們。 您可以編寫一個模式,在其中將構造函數完全應用於其他模式,然后檢查它是否與模式類型的值匹配。 像這樣:
case expr :: EAB
of Var s -> "Var: " <> s
Num n -> "Num: " <> show n
B b -> "B: " <> show b
在該上下文之外,構造函數沒有什么特別的; 它們只是功能1 。 因此,您的Num
是類型為Int -> EAB
的 function,而您的B
是類型為Bool -> EAB
的 function。 您不能以任何方式比較函數。 您可以對 function 做的唯一一件事就是將其應用(應用於正確類型的參數)並查看您得到的結果。
這意味着你想象的vt
是不可能的。 在第三個參數(你說的應該是你沒有定義的Type
)中,你使用了Num
。 但請記住, Num
只是Int -> EAB
類型的 function 。 vt
function 實現無法查看它接收的 function 並測試它是否為Num
以幫助確定返回值應該是True
還是False
。 它唯一可能做的就是將它應用於Int
,然后檢查EAB
值。
但是您可能還希望能夠在該 position 中傳遞B
,以便vt
可以說明給定的EAB
表達式是否可以計算為 boolean 值。 B
是具有不同類型Bool -> EAB
的 function。 vt
的第三個參數接受任一類型 function 的唯一方法是使用類型變量對其進行泛化,使該參數成為(a -> EAB)
。 但是vt
沒有辦法知道這個 function 可以應用到什么地方,所以它甚至不能做你可以用函數做的一件事! 2個
基本上Num
和B
不能用作您語言中類型的抽象表示。 它們是EAB
數據類型中的構造函數,可幫助您使用您的語言構建和檢查值。 這就是他們的全部目的。 因此,真的沒有必要進一步探討為什么不能在列表3 (內部元組)中混合Num
和B
,或者如何解決它。
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除非構造函數沒有 arguments,否則它不是 function。除非通過模式匹配( Eq
實例通過模式匹配簡單實現),否則您仍然無法比較它們。 但是 nullary 構造函數本身就是一個完整的模式,因此不存在您無法比較的未應用的 nullary 構造函數這樣的東西。
2假設我們可以對變量使用類型 class 約束,這可能使調用 function 成為可能。例如,如果它是(Monoid a => a -> EAB)
,那么我們總是可以用mempty
調用它。 不過,您無法對這個想法做任何實際幫助您將此參數用於預期目的的事情,所以我不會 go 在這個方向上進一步。
3但要強調重點:原因與之前相同。 B
和Num
在您使用它們的上下文中只是具有不同類型的函數,您不能在列表中混合不同類型的函數,即使可以,一旦它們在列表中,您也無法對它們執行任何操作(比如查看列表中的每個元組並檢查其中有哪個 function)。
4假設您要使用簡單的值類型,而不是嘗試將Bool -> Bool -> Bool
類的類型分配給未應用的函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.