簡體   English   中英

GADT與數據類型的Haskell模式匹配

[英]Haskell pattern matching on GADTs with Data Kinds

我發現我真的很喜歡將GADT與Data Kinds結合起來,因為它比以前更能提供類型安全性(對於大多數用途,幾乎與Coq,Agda等人一樣好)。 遺憾的是,模式匹配在最簡單的示例中失敗了,我認為除了類型類之外我無法編寫我的函數。

這是一個解釋我的悲傷的例子:

data Nat = Z | S Nat deriving Eq

data Le :: Nat -> Nat -> * where
    Le_base :: Le a a
    Le_S :: Le a b -> Le a (S b)

class ReformOp n m where
    reform :: Le (S n) (S m) -> Le n m

instance ReformOp a a where
    reform Le_base = Le_base

instance ReformOp a b => ReformOp a (S b) where
    reform (Le_S p) = Le_S $ reform p

class TransThm a b c where
    trans :: Le a b -> Le b c -> Le a c

instance TransThm a a a where
    trans = const

instance TransThm a a b => TransThm a a (S b) where
    trans Le_base (Le_S p) = Le_S $ trans Le_base p

instance (TransThm a b c, ReformOp b c) => TransThm a (S b) (S c) where
    trans (Le_S p) q = Le_S $ trans p $ reform q

我們有2個類型類(一個用於定理,一個用於實用操作)和5個實例 - 僅用於一個簡單的定理。 理想情況下,Haskell可以查看此函數:

-- not working, I understand why
trans :: Le a b -> Le b c -> Le a c
trans Le_base Le_base = Le_base
trans Le_base (Le_S p) = Le_S $ trans Le_base p
trans (Le_S p) q = Le_S $ trans p $ reform q

並且trans Le_base Le_base檢查每個子句,並且每次調用決定哪些情況是可能的(因此值得嘗試匹配),哪些不是,所以當調用trans Le_base Le_base Haskell將注意到只有第一種情況允許三個變量是相同的,只嘗試匹配第一個條款。

我怎么沒看到你的模式匹配定義trans將在阿格達或勒柯克工作。

如果您改為編寫以下內容,則可以:

reform :: Le (S n) (S m) -> Le n m
reform Le_base         = Le_base
reform (Le_S Le_base)  = Le_S Le_base
reform (Le_S (Le_S p)) = Le_S (reform (Le_S p))

trans :: Le a b -> Le b c -> Le a c
trans Le_base  q        = q
trans (Le_S p) Le_base  = Le_S p
trans (Le_S p) (Le_S q) = Le_S (trans p (reform (Le_S q)))

當然,您還可以更直接地定義:

trans :: Le a b -> Le b c -> Le a c
trans p Le_base  = p
trans p (Le_S q) = Le_S (trans p q)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM