这是Morte中几乎有效的zipWith
定义:
zipWith
= λ (u : *)
-> λ (f : (u -> u -> u))
-> λ (a : (#List u))
-> λ (b : (#List u))
-> λ (List : *)
-> λ (cons : (u -> List -> List))
-> λ (nil : List)
-> ((λ (A:*) -> λ (B:*) ->
(a (B -> List)
(λ (h:u) -> λ (t : (B -> List) -> λ k : B -> (k h t)))
(λ (k:B) -> nil)
(b (u -> A -> List)
(λ (h:u) -> λ (t:(u -> A -> List)) -> λ (H:u) -> λ (k:A) -> (cons (f h H) (k t)))
(λ (H:u) -> λ (k:A) -> nil)))
) (fix A . ((u -> A -> List) -> List))
(fix B . (u -> (B -> List) -> List)))
由于Morte缺少使用fix
,因此实际上并不是可输入的。 András posted this clever Agda solution without fix
去年。然而,对我而言,它如何转化为Morte并不明显,因为它也缺乏归纳类型。如何解决这个问题?
编辑:使用fix
似乎我的zipWith不正确。 This one似乎在检查。
答案 0 :(得分:6)
为简单起见,我将使用常规的Haskell列表。首先,让我们使用zipWith
定义foldr
:
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = foldr step (const []) xs ys where
step x r [] = []
step x r (y:ys) = f x y : r ys
这里我们折叠xs
,传递ys
作为参数,并在每次迭代时拆分它。问题是我们想要模仿教会编码的列表,但它们不能模式匹配。但是,可以定义split
split :: [a] -> Maybe (a, [a])
split [] = Nothing
split (x:xs) = Just (x, xs)
就foldr
而言:
split :: [a] -> Maybe (a, [a])
split = snd . foldr (\x ~(r, _) -> (x : r, Just (x, r))) ([], Nothing)
现在我们只能使用正确的折叠来定义zipWith
:
czipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
czipWith f xs ys = foldr step (const []) xs ys where
step x r = maybe [] (\(y, ys) -> f x y : r ys) . split
然而,虽然split
懒惰地遍历列表(所以split [1..] ≡ Just (1, [2..])
),但它仍然解构并重建整个列表,因此每个split
引入了O(n)开销,其中{ {1}}是要拆分的列表的长度。由于n
在每次迭代时被分割,因此算法的总复杂度为O(n ^ 2)。
所以是的,您可以只使用非递归类型键入ys
,但它将是O(n ^ 2)。
此外,消除器是依赖的paramorphisms和paramorphisms确实给你模式匹配,所以如果你有消除器,它是straightforward来定义O(n)zipWith
并且它不必那么复杂如在András'回答你链接。
一些阅读:
zipWith
使用split
的{{1}}定义在TAPL中的某处描述。答案 1 :(得分:4)
fix
的聪明定义(来自Launchbury et al.,我相信)在Morte中不起作用,因为键入它而没有负面的递归类型(Morte没有,这意味着什么) O(N^2)
,如我之前的mentioned回答中所述),至少需要对自然数进行归纳。 Here's一个简单的Agda版本的Launchbury定义没有教会编码;要在Morte中重现这一点,我们需要的函数的返回类型取决于自然数(输入列表的长度)。
如果没有归纳,我们可以做的最好的是O(N)
定义,在列表上使用List A -> Maybe (A, List A)
模式匹配,i。即一个O(N)
函数。它是let
,因为我们只能通过从最后重建它来获得列表的尾部。
在Morte兼容的Agda中(为了获得Morte,我们需要将Pair : Set → Set → Set
Pair A B = ∀ P → (A → B → P) → P
pair : ∀ A B → A → B → Pair A B
pair A B a b P p = p a b
List : Set → Set
List = λ A → ∀ L → (A → L → L) → L → L
Maybe : Set → Set
Maybe A = ∀ M → (A → M) → M → M
just : ∀ A → A → Maybe A
just A a M j n = j a
nothing : ∀ A → Maybe A
nothing A M j n = n
nil : ∀ A → List A
nil A L c n = n
cons : ∀ A → A → List A → List A
cons A a as L c n = c a (as L c n)
match : ∀ A → List A → Maybe (Pair A (List A))
match A as =
as
(Maybe (Pair A (List A)))
(λ a m M j n →
m M
(λ p → p M (λ a' as → j (pair A (List A) a (cons A a' as))))
(j (pair A (List A) a (nil A))))
(nothing (Pair A (List A)))
zipWith : ∀ A B C → (A → B → C) → List A → List B → List C
zipWith A B C f as =
as
(List B → List C)
(λ a hyp bs → match B bs (List C)
(λ p → p (List C) (λ b bs' → cons C (f a b) (hyp bs')))
(nil C))
(λ _ → nil C)
样式定义去除应用程序和函数定义到注释的lambdas):
import javax.swing.*;
import java.awt.*;
class calculator{
public static void main(String args[])
{
JFrame frame=new JFrame("Simple Calculator");
JPanel mainpanel=new JPanel();
JPanel tfpanel=new JPanel();
JTextField tf=new JTextField();
tfpanel.add(tf);
tfpanel.setSize(200,40);
tfpanel.setLayout(new GridLayout(0,1));