2015-10-18 12 views
19

Jak systematycznie obliczać liczbę mieszkańców danego typu w Systemie F?Jak systematycznie obliczać liczbę mieszkańców danego typu?

Zakładając następujące ograniczenia:

  • Wszyscy mieszkańcy wypowiedzenia, to znaczy bez dna.
  • Wszyscy mieszkańcy nie mają skutków ubocznych.

na przykład (stosując składni Haskell)

  • Bool dwa mieszkańców.
  • (Bool, Bool) ma czterech mieszkańców.
  • Bool -> (Bool, Bool) ma szesnastu mieszkańców.
  • forall a. a -> a ma jednego mieszkańca.
  • forall a. (a, a) -> (a, a) ma czterech mieszkańców.
  • forall a b. a -> b -> a ma jednego mieszkańca.
  • forall a. a ma zero mieszkańców.

Implementacja algorytmu dla pierwszych trzech jest banalna, ale nie mogę wymyślić, jak to zrobić dla innych.

Odpowiedz

7

Chciałem rozwiązać ten sam problem. Poniższa dyskusja na pewno bardzo mi pomogło:

Abusing the algebra of algebraic data types - why does this work?

Początkowo, ja też był zaniepokojony typów, takich jak forall a. a -> a. Potem miałem objawienie. Zdałem sobie sprawę, że typ forall a. a -> a był Mogensen-Scott encoding z unit type. Stąd miał tylko jednego mieszkańca. Podobnie, forall a. a jest kodowaniem Mogensen-Scott z bottom type. Stąd ma zero mieszkańców. Rozważmy następujące typy danych algebraicznych:

data Bottom       -- forall a. a 

data Unit = Unit     -- forall a. a -> a 

data Bool = False | True   -- forall a. a -> a -> a 

data Nat = Succ Nat | Zero   -- forall a. (a -> a) -> a -> a 

data List a = Cons a (List a) | Nil -- forall a b. (a -> b -> b) -> b -> b 

algebraiczne typ danych jest sum z products. Będę używał składni ⟦τ⟧ do oznaczenia liczby mieszkańców typu τ.Istnieją dwa rodzaje typów Użyję w tym artykule: typy danych F

  1. System, oblicza się według następującego BNF:

    τ = α 
        | τ -> τ 
        | ∀ α. τ 
    
  2. algebraiczne typy danych, oblicza się według następującego BNF:

    τ = 
        | α 
        | τ + τ 
        | τ * τ 
        | μ α. τ 
    

Obliczanie liczby mieszkańców algebraicznych typu danych jest dość prosta:

⟦⟧  = 
⟦τ¹ + τ²⟧ = ⟦τ¹⟧ + ⟦τ²⟧ 
⟦τ¹ * τ²⟧ = ⟦τ¹⟧ * ⟦τ²⟧ 
⟦μ α. τ⟧ = ⟦τ [μ α. τ/α]⟧ 

Rozważmy na przykład listy Typ danych μ β. α * β + 1:

⟦μ β. α * β + 1⟧ = ⟦(α * β + 1) [μ β. α * β + 1/β]⟧ 
       = ⟦α * (μ β. α * β + 1) + 1⟧ 
       = ⟦α * (μ β. α * β + 1)⟧ + ⟦1⟧ 
       = ⟦α⟧ * ⟦μ β. α * β + 1⟧ + ⟦1⟧ 
       = ⟦α⟧ * ⟦μ β. α * β + 1⟧ + 1 

Jednak obliczenia liczby mieszkańców typ danych systemu F nie jest tak prosta. Niemniej jednak można to zrobić. Aby to zrobić, musimy przekonwertować typ danych System F na równoważny algebraiczny typ danych. Na przykład typ danych System F ∀ α. ∀ β. (α -> β -> β) -> β -> β jest odpowiednikiem typu danych listy algebraicznej: μ β. α * β + 1.

Pierwszą rzeczą, aby zauważyć, że chociaż rodzaj systemu F ∀ α. ∀ β. (α -> β -> β) -> β -> β posiada dwie uniwersalne kwantyfikatory jeszcze algebraiczną lista typ danych μ β. α * β + 1 ma tylko jeden (stały punkt) kwantyfikator (czyli algebraiczne typ danych jest lista jednokształtny).

Mimo że możemy utworzyć typ danych listy algebraicznej polimorficznej (tj. ∀ α. μ β. α * β + 1) i dodać regułę ⟦∀ α. τ⟧ = ∀ α. ⟦τ⟧, ale nie robimy tego, ponieważ niepotrzebnie komplikuje sprawy. Zakładamy, że typ polimorficzny został wyspecjalizowany do pewnego typu monomorficznego.

Pierwszym krokiem jest więc usunięcie wszystkich uniwersalnych kwantyfikatorów z wyjątkiem tego, które reprezentuje kwantyfikator "ustalonego punktu". Na przykład typ ∀ α. ∀ β. α -> β -> α staje się ∀ α. α -> β -> α.

Większość konwersji jest prosta ze względu na kodowanie Mogensen-Scotta. Na przykład:

∀ α. α      = μ α. 0     -- bottom type 

∀ α. α -> α     = μ α. 1 + 0    -- unit type 

∀ α. α -> α -> α    = μ α. 1 + 1 + 0   -- boolean type 

∀ α. (α -> α) -> α -> α  = μ α. (α * 1) + 1 + 0  -- natural number type 

∀ β. (α -> β -> β) -> β -> β = μ β. (α * β * 1) + 1 + 0 -- list type 

Niektóre konwersje nie są jednak tak proste. Na przykład ∀ α. α -> β -> α nie reprezentuje prawidłowego typu danych zakodowanych przez Mogensen-Scott. Mimo to, możemy uzyskać prawidłową odpowiedź poprzez żonglowanie typami trochę:

⟦∀ α. α -> β -> α⟧ = ⟦β -> ∀ α. α -> α⟧ 
        = ⟦∀ α. α -> α⟧^⟦β⟧ 
        = ⟦μ α. 1 + 0⟧^⟦β⟧ 
        = ⟦μ α. 1⟧^⟦β⟧ 
        = ⟦1⟧^⟦β⟧ 
        = 1^⟦β⟧ 
        = 1 

dla innych typów musimy użyć kilku sztuczek:

∀ α. (α, α) -> (α, α) = (∀ α. (α, α) -> α, ∀ α. (α, α) -> α) 
         = (∀ α. α -> α -> α, ∀ α. α -> α -> α) 

⟦∀ α. α -> α -> α⟧ = ⟦μ α. 1 + 1 + 0⟧ 
        = ⟦μ α. 2⟧ 
        = ⟦2⟧ 
        = 2 

⟦∀ α. (α, α) -> (α, α)⟧ = ⟦∀ α. α -> α -> α⟧ * ⟦∀ α. α -> α -> α⟧ 
         = 2 * 2 
         = 4 

Chociaż istnieje prosty algorytm, który da nam numer mieszkańców typu kodowanego przez Mogensen-Scott, ale nie mogę wymyślić żadnego ogólnego algorytmu, który da nam liczbę mieszkańców dowolnego typu polimorficznego.

W rzeczywistości mam bardzo silne przeczucie, że obliczanie liczby mieszkańców dowolnego rodzaju polimorficznego jest problemem nierozstrzygalnym. Dlatego uważam, że nie ma algorytmu, który da nam liczbę mieszkańców dowolnego rodzaju polimorficznego w ogóle.

Niemniej jednak uważam, że używanie typów kodowanych przez Mogensen-Scott to świetny początek. Mam nadzieję że to pomoże.

Powiązane problemy