Morte旨在作为超级优化功能程序的中间语言。为了保持强规范化,它没有直接递归,因此,列表等归纳类型表示为折叠,无限列表等导电类型表示为流:
finiteList :: List Int
finiteList = \cons nil -> cons 0 (cons 1 (cons 2 nil))
infiniteList :: Stream Int
infiniteList = Stream 0 (\n -> (n, n + 1))
我想在Morte上重写Haskell' enumFromTo
,以便:
enumFromTo 0 2
规范化为:
\cons nil → cons 0 (cons 1 (cons 2 nil))
这可能吗?
答案 0 :(得分:5)
在Morte中,自然数被编码为类型的值:
forall (Nat : *) -> (Nat -> Nat) -> Nat -> Nat
因此,例如,Morte中的0
,1
和2
将表示为:
( \(Nat : *)
-> \(zero : Nat)
-> \(one : Nat)
-> \(two : Nat)
-> \(foldNat : Nat -> forall (x : *) -> (x -> x) -> x -> x)
-> ...
)
-- Nat
(forall (Nat : *) -> (Nat -> Nat) -> Nat -> Nat)
-- zero
(\(Nat : *) -> \(Succ : Nat -> Nat) -> \(Zero : Nat) -> Zero)
-- one
(\(Nat : *) -> \(Succ : Nat -> Nat) -> \(Zero : Nat) -> Succ Zero)
-- two
(\(Nat : *) -> \(Succ : Nat -> Nat) -> \(Zero : Nat) -> Succ (Succ Zero))
-- foldNat
(\(n : forall (Nat : *) -> (Nat -> Nat) -> Nat -> Nat) -> n)
使用该编码,您可以开始编写简单的内容,例如replicate
:
-- Assuming you also defined:
-- List : * -> *
-- Cons : forall (a : *) -> a -> List a -> List a
-- Nil : forall (a : *) -> List a
-- foldList : forall (a : *)
-- -> List a -> forall (x : *) -> (a -> x -> x) -> x -> x
-- replicate : forall (a : *) -> Nat -> a -> List a
replicate =
\(a : *)
-> \(n : Nat)
-> \(va : a)
-> foldNat n (List a) (\(as : List a) -> Cons a va as) (Nil a)
做enumFromTo
会稍微复杂一点,但仍然可行。您仍然会使用foldNat
,但您的累加器会比List Nat
更复杂。它更像是(Nat, List Nat)
然后你会在折叠结束时提取元组的第二个元素。当然,这也需要在Morte中编码元组。
这超出了我手动编写Morte代码的能力,因此我将省略它。但是,现在我正在研究一种在我们说话时编译为Morte的中级语言,并且它只支持几行代码而不支持递归类型(并且非递归类型已准备就绪)。你可以在这里查看:
https://github.com/Gabriel439/Haskell-Annah-Library
一旦该代码准备就绪,您就可以写下:
type Nat : *
data Succ (pred : Nat) : Nat
data Zero : Nat
in
type List (a : *) : *
data Cons (head : a) (tail : List a) : List a
data Nil : List a
in
let One : Nat = Succ Zero
let Two : Nat = Succ (Succ Zero)
let Three : Nat = Succ (Succ (Succ Zero))
let replicate (a : *) (n : Nat) (va : a) : List a =
foldNat n (List a) (\(as : List a) -> Cons a va as) (Nil a)
in
replicate Nat Two Three
在某种意义上说,你仍然需要明确地写出一个折叠并找出用作累加器的正确中间状态,这是中等水平,但它简化的一个问题是let
和数据类型声明。它最终也会支持Nat
的内置十进制语法,但我还没有开始。
编辑:现在annah
支持递归类型,上面的annah
代码规范化为:
$ annah < replicate.an
∀(List : * → *) → ((∀(Nat : *) → (Nat → Nat) → Nat → Nat) → List (∀(Nat : *) → (Nat → Nat) → Nat → Nat) → List (∀(Nat : *) → (Nat → Nat) → Nat → Nat)) → List (∀(Nat : *) → (Nat → Nat) → Nat → Nat) → List (∀(Nat : *) → (Nat → Nat) → Nat → Nat)
λ(List : * → *) → λ(Cons : (∀(Nat : *) → (Nat → Nat) → Nat → Nat) → List (∀(Nat : *) → (Nat → Nat) → Nat → Nat) → List (∀(Nat : *) → (Nat → Nat) → Nat → Nat)) → λ(Nil : List (∀(Nat : *) → (Nat → Nat) → Nat → Nat)) → Cons (λ(Nat : *) → λ(Succ : Nat → Nat) → λ(Zero : Nat) → Succ (Succ (Succ Zero))) (Cons (λ(Nat : *) → λ(Succ : Nat → Nat) → λ(Zero : Nat) → Succ (Succ (Succ Zero))) Nil)
...我将格式化以使其更具可读性:
λ(List : * → *)
→ λ( Cons
: (∀(Nat : *) → (Nat → Nat) → Nat → Nat)
→ List (∀(Nat : *) → (Nat → Nat) → Nat → Nat)
→ List (∀(Nat : *) → (Nat → Nat) → Nat → Nat)
)
→ λ(Nil : List (∀(Nat : *) → (Nat → Nat) → Nat → Nat))
→ Cons
( λ(Nat : *)
→ λ(Succ : Nat → Nat)
→ λ(Zero : Nat)
→ Succ (Succ (Succ Zero))
)
(Cons
( λ(Nat : *)
→ λ(Succ : Nat → Nat)
→ λ(Zero : Nat)
→ Succ (Succ (Succ Zero))
)
Nil
)
如果你仔细观察,它会产生一个包含两个元素的列表,每个元素都是一个教会编码的三号。