簡體   English   中英

對於非常規遞歸類型,catamorphism(fold)的類型是什么?

[英]What's the type of a catamorphism (fold) for non-regular recursive types?

許多catamorphisms似乎很簡單,大多數用自定義函數替換每個數據構造函數,例如

data Bool = False | True
foldBool :: r              -- False constructor
         -> r              -- True constructor
         -> Bool -> r

data Maybe a = Nothing | Just a
foldMaybe :: b             -- Nothing constructor
          -> (a -> b)      -- Just constructor
          -> Maybe a -> b

data List a = Empty | Cons a (List a)
foldList :: b              -- Empty constructor
         -> (a -> b -> b)  -- Cons constructor
         -> List a -> b

但是,對我來說不清楚的是,如果使用相同類型的構造函數,但使用不同的類型參數會發生什么。 例如,不是將List a傳遞給Cons ,而是將其傳遞給Cons

data List a = Empty | Cons a (List (a,a))

或者,也許是一個更瘋狂的案例:

data List a = Empty | Cons a (List (List a))
foldList :: b              -- Empty constructor
         -> ???            -- Cons constructor
         -> List a -> b

我有兩個看似合理的想法??? 部分是

  • (a -> b -> b) ,即遞歸替換List構造函數的所有應用程序)
  • (a -> List b -> b) ,即僅替換所有List a應用程序。

哪兩個是正確的 - 為什么? 或者它會完全不同嗎?

這只是部分答案。

OP提出的問題是:如何在非常規遞歸類型的情況下定義fold / cata

由於我不相信自己這么做,我會求助於Coq。 讓我們從一個簡單的,常規的遞歸列表類型開始。

Inductive List (A : Type) : Type :=
  | Empty: List A
  | Cons : A -> List A -> List A
.

沒有什么花哨的, List A是根據List A定義List A (記住這一點 - 我們會回復它。)

怎么樣的cata 讓我們查詢歸納原理。

> Check List_rect.
forall (A : Type) (P : List A -> Type),
   P (Empty A) ->
   (forall (a : A) (l : List A), P l -> P (Cons A a l)) ->
   forall l : List A, P l

讓我們來看看。 以上利用依賴類型: P取決於列表的實際值。 P list是常數類型B的情況下,讓我們手動簡化它。 我們獲得:

forall (A : Type) (B : Type),
   B ->
   (forall (a : A) (l : List A), B -> B) ->
   forall l : List A, B

可以等效地寫成

forall (A : Type) (B : Type),
   B ->
   (A -> List A -> B -> B) ->
   List A -> B

哪個是foldr除了“當前列表”也傳遞給二元函數參數 - 不是主要區別。

現在,在Coq中,我們可以用另一種巧妙的方式定義一個列表:

Inductive List2 : Type -> Type :=
  | Empty2: forall A, List2 A
  | Cons2 : forall A, A -> List2 A -> List2 A
.

它看起來是相同的類型,但有一個深刻的區別。 在這里,我們不是在定義類型List A中的條款List A 相反,我們定義了一個類型函數List2 : Type -> Type of List2 這一點的主要觀點是對List2的遞歸引用不必應用於A - 事實上,我們這樣做只是一個事件。

無論如何,讓我們看一下歸納原理的類型:

> Check List2_rect.
forall P : forall T : Type, List2 T -> Type,
   (forall A : Type, P A (Empty2 A)) ->
   (forall (A : Type) (a : A) (l : List2 A), P A l -> P A (Cons2 A a l)) ->
   forall (T : Type) (l : List2 T), P T l

讓我們像之前一樣從P刪除List2 T參數,基本上假設P是常量。

forall P : forall T : Type, Type,
   (forall A : Type, P A ) ->
   (forall (A : Type) (a : A) (l : List2 A), P A -> P A) ->
   forall (T : Type) (l : List2 T), P T

等效改寫:

forall P : (Type -> Type),
   (forall A : Type, P A) ->
   (forall (A : Type), A -> List2 A -> P A -> P A) ->
   forall (T : Type), List2 T -> P T

在Haskell表示法中大致對應

(forall a, p a) ->                          -- Empty
(forall a, a -> List2 a -> p a -> p a) ->   -- Cons
List2 t -> p t

不是那么糟糕 - 基本情況現在必須是一個多態函數,就像Haskell中的Empty 這有點道理。 同樣,歸納案例必須是多態函數,就像Cons 還有一個額外的List2 a參數,但如果需要,我們可以忽略它。

現在,上面仍然是常規類型的折疊/ cata。 那些非常規的呢? 我會學習

data List a = Empty | Cons a (List (a,a))

在Coq成為:

Inductive  List3 : Type -> Type :=
  | Empty3: forall A, List3 A
  | Cons3 : forall A, A -> List3 (A * A) -> List3 A
.

具有歸納原理:

> Check List3_rect.
forall P : forall T : Type, List3 T -> Type,
   (forall A : Type, P A (Empty3 A)) ->
   (forall (A : Type) (a : A) (l : List3 (A * A)), P (A * A) l -> P A (Cons3 A a l)) ->
   forall (T : Type) (l : List3 T), P T l

刪除“依賴”部分:

forall P : (Type -> Type),
   (forall A : Type, P A) ->
   (forall (A : Type), A -> List3 (A * A) -> P (A * A) -> P A ) ->
   forall (T : Type), List3 T -> P T

在Haskell表示法中:

   (forall a. p a) ->                                      -- empty
   (forall a, a -> List3 (a, a) -> p (a, a) -> p a ) ->    -- cons
   List3 t -> p t

除了附加的List3 (a, a)參數之外,這是一種折疊。

最后,OP類型怎么樣?

data List a = Empty | Cons a (List (List a))

唉,Coq不接受這種類型

Inductive  List4 : Type -> Type :=
  | Empty4: forall A, List4 A
  | Cons4 : forall A, A -> List4 (List4 A) -> List4 A
.

因為內部List4發生不在嚴格的正位置。 這可能暗示我應該停止懶惰並使用Coq來完成工作,並開始自己考慮所涉及的F-algebras ... ;-)

暫無
暫無

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

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