• Keine Ergebnisse gefunden

dannist candidate korrektfürassoziatives ⊕ aufbeliebigemTyp. [( Zero , ) One , Two ( , Zero ) ] und candidate ( ⊕ ) istkorrektaufjederListederForm [( Zero , ) One ( , Zero ) ( , Two ) ] candidate ( ⊕ ) korrektaufjederListederForm ⊕ ZeroOneTwoZeroZeroOneTw

N/A
N/A
Protected

Academic year: 2022

Aktie "dannist candidate korrektfürassoziatives ⊕ aufbeliebigemTyp. [( Zero , ) One , Two ( , Zero ) ] und candidate ( ⊕ ) istkorrektaufjederListederForm [( Zero , ) One ( , Zero ) ( , Two ) ] candidate ( ⊕ ) korrektaufjederListederForm ⊕ ZeroOneTwoZeroZeroOneTw"

Copied!
95
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Wie? So!

Es seien

1 Zero One Two Zero Zero One Two One One Two Two Two Two Two Two

und

2 Zero One Two Zero Zero One Two One One One Two Two Two One Two Istcandidate (⊕1) korrekt auf jeder Liste der Form

[(Zero,) One(,Zero) (,Two)] undcandidate (⊕2)ist korrekt auf jeder Liste der Form

[(Zero,) One,Two (,Zero)]

dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

(2)

Ein Knuth-ähnliches 0-1-2-Prinzip

Gegeben: scanl1:: (α→α→α)→[α]→[α]

scanl1(⊕) (x :xs) =go x xs where go x [ ] = [x]

go x (y :ys) =x :go (x⊕y) ys candidate:: (α→α→α)→[α]→[α]

dataThree=Zero |One|Two

Theorem: Wenn für jedesxs:: [Three]und assoziatives (⊕) ::Three→Three→Three,

candidate (⊕) xs = scanl1(⊕) xs, dann gilt das Gleiche für jeden Typτ,xs:: [τ], und assoziatives(⊕) ::τ →τ →τ.

(3)

Verwendung des Theorem-Generators

Eingabe: candidate :: (a -> a -> a) -> [a] -> [a]

Ausgabe: forall t1,t2 in TYPES, f :: t1 -> t2.

forall p :: t1 -> t1 -> t1.

forall q :: t2 -> t2 -> t2.

(forall x :: t1. forall y :: t1.

f (p x y) = q (f x) (f y))

==> (forall z :: [t1].

map f (candidate p z)

= candidate q (map f z))

(4)

Anders ausgedrückt

Für jede Wahl von Typenτ1, τ2 und Funktionen f ::τ1 →τ2, (⊗) ::τ1 →τ1 →τ1 und (⊕) ::τ2→τ2 →τ2:

τ1×τ1 τ11] [τ1]

= ⇒ =

τ2×τ2 τ22] [τ2]

⊗ f × f

f

candidate(⊗)

mapf map f

candidate(⊕)

(5)

Ein Knuth-ähnliches 0-1-2-Prinzip

Gegeben: scanl1:: (α→α→α)→[α]→[α]

scanl1(⊕) (x :xs) =go x xs where go x [ ] = [x]

go x (y :ys) =x :go (x⊕y) ys candidate:: (α→α→α)→[α]→[α]

dataThree=Zero |One|Two

Theorem: Wenn für jedesxs:: [Three]und assoziatives (⊕) ::Three→Three→Three,

candidate (⊕) xs = scanl1(⊕) xs, dann gilt das Gleiche für jeden Typτ,xs:: [τ], und assoziatives(⊕) ::τ →τ →τ.

(6)

Dekomponieren des 0-1-2-Prinzips

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form[(Zero,) One(,Zero) (,Two)]undcandidate (⊕2) korrekt ist für jede Liste der Form[(Zero,) One,Two (,Zero)], dann gilt für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]] (*).

Aussage 2:Wenn (*) für jedesn≥0 gilt, dann ist candidate korrekt für assoziatives⊕auf beliebigem Typ.

(7)

Dekomponieren des 0-1-2-Prinzips

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form[(Zero,) One(,Zero) (,Two)]undcandidate (⊕2) korrekt ist für jede Liste der Form[(Zero,) One,Two (,Zero)], dann gilt für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]] (*).

Aussage 2:Wenn (*) für jedesn≥0 gilt, dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

(8)

Dekomponieren des 0-1-2-Prinzips

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form[(Zero,) One(,Zero) (,Two)]undcandidate (⊕2) korrekt ist für jede Liste der Form[(Zero,) One,Two (,Zero)], dann gilt für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]] (*).

Aussage 2:Wenn (*) für jedesn≥0 gilt, dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

τ1×τ1 τ11] [τ1]

= ⇒ =

τ2×τ2 τ22] [τ2]

⊗ f × f

f

candidate(⊗)

mapf map f

candidate(⊕)

(9)

Dekomponieren des 0-1-2-Prinzips

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form[(Zero,) One(,Zero) (,Two)]undcandidate (⊕2) korrekt ist für jede Liste der Form[(Zero,) One,Two (,Zero)], dann gilt für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]] (*).

Aussage 2:Wenn (*) für jedesn≥0 gilt, dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

[Int]×[Int] [Int] [[Int]] [[Int]]

= ⇒ =

τ2×τ2 τ22] [τ2]

++

f × f

f

candidate(++)

mapf mapf

candidate(⊕) ::

[[k]|k ←[0..n]]

(10)

Formaler Beweis

Seixs :: [τ2]mit Länge (n+1).

Dann ist für f =foldl1(⊕) ◦ map (xs!!) die Vorbedingung von

[Int]×[Int] [Int] [[Int]] [[Int]]

= ⇒ =

τ2×τ2 τ22] [τ2]

++

f × f

f

candidate(++)

mapf mapf

candidate(⊕) ::

[[k]|k ←[0..n]]

erfüllt, sofern⊕assoziativ. Also dann:

map f (candidate (++)[[k] |k←[0..n]])

= candidate(⊕) (mapf [[k]|k ←[0..n]])

= candidate(⊕) xs

(11)

Formaler Beweis

Seixs :: [τ2]mit Länge (n+1). Dann ist für f =foldl1(⊕) ◦ map (xs!!) die Vorbedingung von

[Int]×[Int] [Int] [[Int]] [[Int]]

= ⇒ =

τ2×τ2 τ22] [τ2]

++

f × f

f

candidate(++)

mapf mapf

candidate(⊕) ::

[[k]|k ←[0..n]]

erfüllt, sofern⊕assoziativ. Also dann:

map f (candidate (++)[[k] |k←[0..n]])

= candidate(⊕) (mapf [[k]|k ←[0..n]])

= candidate(⊕) xs

(12)

Formaler Beweis

Seixs :: [τ2]mit Länge (n+1). Dann ist für f =foldl1(⊕) ◦ map (xs!!) die Vorbedingung von

[Int]×[Int] [Int] [[Int]] [[Int]]

= ⇒ =

τ2×τ2 τ22] [τ2]

++

f × f

f

candidate(++)

mapf mapf

candidate(⊕) ::

[[k]|k ←[0..n]]

erfüllt, sofern⊕assoziativ.

Also dann:

map f (candidate (++)[[k] |k←[0..n]])

= candidate(⊕) (mapf [[k]|k ←[0..n]])

= candidate(⊕) xs

(13)

Formaler Beweis

Seixs :: [τ2]mit Länge (n+1). Dann ist für f =foldl1(⊕) ◦ map (xs!!) die Vorbedingung von

[Int]×[Int] [Int] [[Int]] [[Int]]

= ⇒ =

τ2×τ2 τ22] [τ2]

++

f × f

f

candidate(++)

mapf mapf

candidate(⊕) ::

[[k]|k ←[0..n]]

erfüllt, sofern⊕assoziativ.

Also dann:

map f (candidate (++)[[k] |k ←[0..n]])

= candidate(⊕) (mapf [[k]|k ←[0..n]])

= candidate(⊕) xs

(14)

Formaler Beweis

Seixs :: [τ2]mit Länge (n+1). Dann ist für f =foldl1(⊕) ◦ map (xs!!) die Vorbedingung von

[Int]×[Int] [Int] [[Int]] [[Int]]

= ⇒ =

τ2×τ2 τ22] [τ2]

++

f × f

f

candidate(++)

mapf mapf

candidate(⊕) ::

[[k]|k ←[0..n]]

erfüllt, sofern⊕assoziativ.

Also dann:

map f (candidate (++)[[k] |k ←[0..n]])

= candidate(⊕) (mapf [[k]|k ←[0..n]])

= candidate(⊕) xs

(15)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(16)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(17)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(18)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k ←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(19)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k ←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(20)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k ←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(21)

Formaler Beweis

Aussage 2:Wenn für jedesn≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k]|k ←[0..n]], dann istcandidate korrekt für assoziatives⊕auf beliebigem Typ.

Beweis:

candidate (⊕) xs

= map f (candidate (++)[[k]|k ←[0..n]])

= map f [[0..k]|k ←[0..n]]

= map (foldl1(⊕)◦ map (xs!!)) [[0..k] |k ←[0..n]]

= [foldl1(⊕) (map (xs!!) [0..k])|k ←[0..n]]

= [foldl1(⊕) (take (k+1) xs) |k ←[0..n]]

= scanl1(⊕) xs

(22)

Formaler Beweis

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form. . . undcandidate (⊕2) korrekt ist für jede Liste der Form . . ., dann gilt für jedes n≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]].

Beweis:

Wir wissen, für allep,q,r≥0:

map (foldl1(⊕1) ◦ map ([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r] und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1] . . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(23)

Formaler Beweis

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form. . . undcandidate (⊕2) korrekt ist für jede Liste der Form . . ., dann gilt für jedes n≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]]. Beweis:

Wir wissen, für allep,q,r ≥0:

map (foldl1(⊕1) ◦ map([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r] und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1] . . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(24)

Formaler Beweis

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form. . . undcandidate (⊕2) korrekt ist für jede Liste der Form . . ., dann gilt für jedes n≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]]. Beweis:

Wir wissen, für allep,q,r ≥0:

map (foldl1(⊕1) ◦ map([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r]

und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1] . . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(25)

Formaler Beweis

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form. . . undcandidate (⊕2) korrekt ist für jede Liste der Form . . ., dann gilt für jedes n≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]]. Beweis:

Wir wissen, für allep,q,r ≥0:

map (foldl1(⊕1) ◦ map([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r] und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1] . . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(26)

Formaler Beweis

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form. . . undcandidate (⊕2) korrekt ist für jede Liste der Form . . ., dann gilt für jedes n≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]]. Beweis:

Wir wissen, für allep,q,r ≥0:

map (foldl1(⊕1) ◦ map([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r] und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1]

. . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(27)

Formaler Beweis

Aussage 1:Wenncandidate(⊕1)korrekt ist für jede Liste der Form. . . undcandidate (⊕2) korrekt ist für jede Liste der Form . . ., dann gilt für jedes n≥0,

candidate(++) [[k]|k ←[0..n]] = [[0..k] |k←[0..n]]. Beweis:

Wir wissen, für allep,q,r ≥0:

map (foldl1(⊕1) ◦ map([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r] und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1] . . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(28)

Formaler Beweis

Beweis:

Wir wissen, für allep,q,r ≥0:

map (foldl1(⊕1) ◦ map([(Zero,)p One(,Zero)q (,Two)r] !!)) (candidate(++)[[k]|k ←[0..(p+q+r)]])

= [(Zero,)p (One,)q+1 (Two,)r] und:

map (foldl1(⊕2) ◦ map ([(Zero,)p One,Two(,Zero)q] !!)) (candidate(++)[[k]|k ←[0..(p+q+1)]])

= [(Zero,)p One(,Two)q+1] . . .

Detailliert in [V. 2008], sowie in einem Theorembeweiser formalisiert [Böhme,http://afp.sf.net/entries/MuchAdoAboutTwo.shtml].

(29)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

(30)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

update

(31)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

(32)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

(33)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

(34)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel: get=flat

View-Update:

(35)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel: get=flat View-Update:

‘a’ ‘b’ ‘a’ ‘c’

“abac”

‘a’ ‘b’ ‘x’ ‘c’

“abxc”

flat

(36)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel: get=flat View-Update:

‘a’ ‘b’ ‘a’ ‘c’

“abac”

‘a’ ‘b’ ‘x’ ‘c’

“abxc”

flat

update

(37)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel: get=flat View-Update:

‘a’ ‘b’ ‘a’ ‘c’

“abac”

‘a’ ‘b’ ‘x’ ‘c’

“abxc”

flat

flat1

update

(38)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

(39)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

=

Acceptability / GetPut

(40)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

=

Acceptability / GetPut

(41)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

Consistency / PutGet

(42)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

get

Consistency / PutGet

(43)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

(44)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel 1:

halve:: [α]→[α]

halve as =take (lengthas ‘div‘ 2) as

halve1:: [α]→[α]→[α]

halve1 as as0 | lengthas0==n

=as0++dropn as

where n=lengthas ‘div‘ 2

(45)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel 1:

halve:: [α]→[α]

halve as =take (lengthas ‘div‘ 2) as halve1:: [α]→[α]→[α]

halve1 as as0 | lengthas0==n

=as0++dropn as

where n=lengthas ‘div‘ 2

(46)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel 2:

flat::Tree α→[α]

flat (Leaf a) = [a]

flat (Nodet1 t2) = (flatt1) ++(flatt2)

flat1 ::Tree α→[α]→Treeα flat1 s v =casego s v of (t,[ ])→t

where go (Leaf a) (b :bs) = (Leaf b,bs) go (Nodes1 s2) bs = (Nodet1 t2,ds)

where(t1,cs) =go s1 bs (t2,ds) =go s2 cs

(47)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel 2:

flat::Tree α→[α]

flat (Leaf a) = [a]

flat (Nodet1 t2) = (flatt1) ++(flatt2) flat1 ::Tree α→[α]→Treeα

flat1 s v =casego s v of (t,[ ])→t where go (Leaf a) (b:bs) = (Leaf b,bs)

go (Nodes1 s2) bs = (Nodet1 t2,ds) where(t1,cs) =go s1 bs

(t2,ds) =go s2 cs

(48)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel 3:

rmdups::Eq α⇒[α]→[α]

rmdups=List.nub

rmdups1 ::Eq α⇒[α]→[α]→[α]

rmdups1 s v | v ==List.nubv && lengthv ==lengths0

=map(fromJust◦flip lookup(zips0 v))s wheres0=List.nub s

(49)

Eine weitere Anwendung: Bidirektionalisierung

Beispiel 3:

rmdups::Eq α⇒[α]→[α]

rmdups=List.nub

rmdups1 ::Eq α⇒[α]→[α]→[α]

rmdups1 s v | v ==List.nubv && lengthv ==lengths0

=map(fromJust◦flip lookup(zips0 v))s wheres0=List.nub s

(50)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

(51)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

Syntaktische

Bidirektionalisierung

(52)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

Syntaktische Bidirektionalisierung

(53)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

?

Semantische Bidirektionalisierung

(54)

Eine weitere Anwendung: Bidirektionalisierung

source view

s v

s v

get

put

update

X

Semantische Bidirektionalisierung

(55)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bffso dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . .

Beispiele:

“ Bidirectionalization for free!”

(56)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . .

Beispiele:

“ Bidirectionalization for free!”

(57)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

“abc” “bc”

“ade” “de”

tail

“ Bidirectionalization for free!”

(58)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

“abc” “bc”

“ade” “de”

tail

update

“ Bidirectionalization for free!”

(59)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

“abc” “bc”

“ade” “de”

tail

bff tail

update

“ Bidirectionalization for free!”

(60)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

‘a’ ‘b’ ‘a’ ‘c’

“abac”

‘a’ ‘b’ ‘x’ ‘c’

“abxc”

flat

“ Bidirectionalization for free!”

(61)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

‘a’ ‘b’ ‘a’ ‘c’

“abac”

‘a’ ‘b’ ‘x’ ‘c’

“abxc”

flat

update

“ Bidirectionalization for free!”

(62)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

‘a’ ‘b’ ‘a’ ‘c’

“abac”

‘a’ ‘b’ ‘x’ ‘c’

“abxc”

flat

bff flat

update

“ Bidirectionalization for free!”

(63)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

‘a’ ‘b’ ‘a’ ‘c’

“abc”

‘x’ ‘b’ ‘x’ ‘c’

“xbc”

nub◦flatten

“ Bidirectionalization for free!”

(64)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

‘a’ ‘b’ ‘a’ ‘c’

“abc”

‘x’ ‘b’ ‘x’ ‘c’

“xbc”

nub◦flatten

update

“ Bidirectionalization for free!”

(65)

Semantische Bidirektionalisierung

Ziel: Schreibe eine Higher-Order Funktion bff so dass jeweils fürgetund bff get gilt: GetPut, PutGet, . . . Beispiele:

‘a’ ‘b’ ‘a’ ‘c’

“abc”

‘x’ ‘b’ ‘x’ ‘c’

“xbc”

nub◦flatten

bff (nub◦flatten)

update

“ Bidirectionalization for free!”

(66)

Analyse spezifischer Aufrufe

Angenommen, es sei gegeben:

get:: [α]→[α]

Wie können wir, oderbff, die Funktion analysieren ohne Zugriff auf ihren Quellcode?

Idee:Wie wäre es damit,get für „irgendeine“ Eingabe aufzurufen? Etwa:

get [0..n] =









[1..n] ifget=tail

[n..0] ifget=reverse [0..(min 4 n)] ifget=take5

...

Dann, Übertragung der Erkenntnisse auf andere Listen als[0..n]!

(67)

Analyse spezifischer Aufrufe

Angenommen, es sei gegeben:

get:: [α]→[α]

Wie können wir, oderbff, die Funktion analysieren ohne Zugriff auf ihren Quellcode?

Idee:Wie wäre es damit,get für „irgendeine“ Eingabe aufzurufen? Etwa:

get [0..n] =









[1..n] ifget=tail

[n..0] ifget=reverse [0..(min 4 n)] ifget=take5

...

Dann, Übertragung der Erkenntnisse auf andere Listen als[0..n]!

(68)

Analyse spezifischer Aufrufe

Angenommen, es sei gegeben:

get:: [α]→[α]

Wie können wir, oderbff, die Funktion analysieren ohne Zugriff auf ihren Quellcode?

Idee:Wie wäre es damit,get für „irgendeine“ Eingabe aufzurufen?

Etwa:

get [0..n] =









[1..n] ifget=tail

[n..0] ifget=reverse [0..(min 4 n)] ifget=take5

...

Dann, Übertragung der Erkenntnisse auf andere Listen als[0..n]!

(69)

Analyse spezifischer Aufrufe

Angenommen, es sei gegeben:

get:: [α]→[α]

Wie können wir, oderbff, die Funktion analysieren ohne Zugriff auf ihren Quellcode?

Idee:Wie wäre es damit,get für „irgendeine“ Eingabe aufzurufen?

Etwa:

get [0..n] =









[1..n] ifget=tail

[n..0] ifget=reverse [0..(min 4n)] ifget=take5

...

Dann, Übertragung der Erkenntnisse auf andere Listen als[0..n]!

(70)

Analyse spezifischer Aufrufe

Angenommen, es sei gegeben:

get:: [α]→[α]

Wie können wir, oderbff, die Funktion analysieren ohne Zugriff auf ihren Quellcode?

Idee:Wie wäre es damit,get für „irgendeine“ Eingabe aufzurufen?

Etwa:

get [0..n] =









[1..n] ifget=tail

[n..0] ifget=reverse [0..(min 4n)] ifget=take5

...

Dann, Übertragung der Erkenntnisse auf andere Listen als[0..n]!

(71)

Verwendung eines freien Theorems

Für jedes

g:: [α]→[α]

gilt:

map f (gl) = g (map f l) für beliebigef undl.

(72)

Verwendung eines freien Theorems

Für jedes

g:: [α]→[α]

gilt:

map f (gl) = g (map f l) für beliebigef undl.

Für eine beliebige Listes der Längen+1, setzeg=get,l = [0..n], f = (s!!), woraus sich ergibt:

map (s!!) (get [0..n]) = get (map (s!!) [0..n])

| {z }

= get s

(73)

Verwendung eines freien Theorems

Für jedes

g:: [α]→[α]

gilt:

map f (gl) = g (map f l) für beliebigef undl.

Für eine beliebige Listes der Längen+1, setzeg=get,l = [0..n], f = (s!!), woraus sich ergibt:

map (s!!) (get [0..n]) = get (map (s!!) [0..n])

| {z }

= get s

(74)

Verwendung eines freien Theorems

Für jedes

g:: [α]→[α]

gilt:

map f (gl) = g (map f l) für beliebigef undl.

Für eine beliebige Listes der Längen+1,

setzeg=get,l = [0..n], f = (s!!), woraus sich ergibt:

map (s!!) (get [0..n])

= get (map (s!!) [0..n])

| {z }

= get s

(75)

Verwendung eines freien Theorems

Für jedes

g:: [α]→[α]

gilt:

map f (gl) = g (map f l) für beliebigef undl.

Für eine beliebige Listes der Längen+1,

setzeg=get,l = [0..n], f = (s!!), woraus sich ergibt:

gets = map (s!!) (get [0..n]) für jedesget:: [α]→[α].

(76)

Der „Constant-Complement“ Ansatz [Bancilhon & Spyratos 1981]

Allgemein, für

get::S →V

definiere einVC und

compl::S →VC so dass

λs →(get s,compls) injektiv ist und ein Inverses hat:

inv:: (V,VC)→S Dann:

put::S →V →S

put s v0 =inv (v0,compls)

Wichtig:compl sollte so „nicht-injektiv“ wie möglich sein.

(77)

Der „Constant-Complement“ Ansatz [Bancilhon & Spyratos 1981]

Allgemein, für

get::S →V definiere einVC und

compl::S →VC

so dass

λs →(get s,compls) injektiv ist und ein Inverses hat:

inv:: (V,VC)→S Dann:

put::S →V →S

put s v0 =inv (v0,compls)

Wichtig:compl sollte so „nicht-injektiv“ wie möglich sein.

(78)

Der „Constant-Complement“ Ansatz [Bancilhon & Spyratos 1981]

Allgemein, für

get::S →V definiere einVC und

compl::S →VC so dass

λs →(get s,compls) injektiv ist

und ein Inverses hat:

inv:: (V,VC)→S Dann:

put::S →V →S

put s v0 =inv (v0,compls)

Wichtig:compl sollte so „nicht-injektiv“ wie möglich sein.

(79)

Der „Constant-Complement“ Ansatz [Bancilhon & Spyratos 1981]

Allgemein, für

get::S →V definiere einVC und

compl::S →VC so dass

λs →(get s,compls) injektiv ist und ein Inverses hat:

inv:: (V,VC)→S

Dann:

put::S →V →S

put s v0 =inv (v0,compls)

Wichtig:compl sollte so „nicht-injektiv“ wie möglich sein.

(80)

Der „Constant-Complement“ Ansatz [Bancilhon & Spyratos 1981]

Allgemein, für

get::S →V definiere einVC und

compl::S →VC so dass

λs →(get s,compls) injektiv ist und ein Inverses hat:

inv:: (V,VC)→S Dann:

put::S →V →S

put s v0 =inv (v0,compls)

Wichtig:compl sollte so „nicht-injektiv“ wie möglich sein.

(81)

Der „Constant-Complement“ Ansatz [Bancilhon & Spyratos 1981]

Allgemein, für

get::S →V definiere einVC und

compl::S →VC so dass

λs →(get s,compls) injektiv ist und ein Inverses hat:

inv:: (V,VC)→S Dann:

put::S →V →S

put s v0 =inv (v0,compls)

Wichtig:compl sollte so „nicht-injektiv“ wie möglich sein.

(82)

Der „Constant-Complement“ Ansatz

Für unseren Fall,

get:: [α]→[α], was sollten wir wählen fürVC und

compl:: [α]→VC ???

Um

λs →(get s,compls)

injektiv zu kriegen, müssen Informationen festgehalten werden, welcheget verwirft.

Kandidaten:

1. Länge der ursprünglichen Liste 2. verworfene Listenelemente

Für den Augenblick, seien wir möglichst konservativ.

(83)

Der „Constant-Complement“ Ansatz

Für unseren Fall,

get:: [α]→[α], was sollten wir wählen fürVC und

compl:: [α]→VC ???

Um

λs →(get s,compls)

injektiv zu kriegen, müssen Informationen festgehalten werden, welcheget verwirft.

Kandidaten:

1. Länge der ursprünglichen Liste 2. verworfene Listenelemente

Für den Augenblick, seien wir möglichst konservativ.

(84)

Der „Constant-Complement“ Ansatz

Für unseren Fall,

get:: [α]→[α], was sollten wir wählen fürVC und

compl:: [α]→VC ???

Um

λs →(get s,compls)

injektiv zu kriegen, müssen Informationen festgehalten werden, welcheget verwirft.

Kandidaten:

1. Länge der ursprünglichen Liste

2. verworfene Listenelemente

Für den Augenblick, seien wir möglichst konservativ.

(85)

Der „Constant-Complement“ Ansatz

Für unseren Fall,

get:: [α]→[α], was sollten wir wählen fürVC und

compl:: [α]→VC ???

Um

λs →(get s,compls)

injektiv zu kriegen, müssen Informationen festgehalten werden, welcheget verwirft.

Kandidaten:

1. Länge der ursprünglichen Liste 2. verworfene Listenelemente

Für den Augenblick, seien wir möglichst konservativ.

(86)

Der „Constant-Complement“ Ansatz

Für unseren Fall,

get:: [α]→[α], was sollten wir wählen fürVC und

compl:: [α]→VC ???

Um

λs →(get s,compls)

injektiv zu kriegen, müssen Informationen festgehalten werden, welcheget verwirft.

Kandidaten:

1. Länge der ursprünglichen Liste 2. verworfene Listenelemente

Für den Augenblick, seien wir möglichst konservativ.

(87)

Die Komplement-Funktion

typeIntMap α= [(Int, α)]

compl:: [α]→(Int,IntMapα) compls =letn = (length s)−1

t = [0..n] g =zip t s

g0 =filter(λ(i,_)→notElemi (gett)) g in (n+1,g0)

Zum Beispiel:

get=tail compl “abcde” = (5,[(0,’a’)])

get=take3 compl “abcde” = (5,[(3,’d’),(4,’e’)]) get=reverse compl “abcde” = (5,[ ])

(88)

Die Komplement-Funktion

typeIntMap α= [(Int, α)]

compl:: [α]→(Int,IntMapα) compls =letn = (length s)−1

t = [0..n] g =zip t s

g0 =filter(λ(i,_)→notElemi (gett)) g in (n+1,g0)

Zum Beispiel:

get=tail compl “abcde” = (5,[(0,’a’)])

get=take3 compl “abcde” = (5,[(3,’d’),(4,’e’)]) get=reverse compl “abcde” = (5,[ ])

(89)

Die Komplement-Funktion

typeIntMap α= [(Int, α)]

compl:: [α]→(Int,IntMapα) compls =letn = (length s)−1

t = [0..n] g =zip t s

g0 =filter(λ(i,_)→notElemi (gett)) g in (n+1,g0)

Zum Beispiel:

get=tail compl “abcde” = (5,[(0,’a’)])

get=take3 compl “abcde” = (5,[(3,’d’),(4,’e’)])

get=reverse compl “abcde” = (5,[ ])

(90)

Die Komplement-Funktion

typeIntMap α= [(Int, α)]

compl:: [α]→(Int,IntMapα) compls =letn = (length s)−1

t = [0..n] g =zip t s

g0 =filter(λ(i,_)→notElemi (gett)) g in (n+1,g0)

Zum Beispiel:

get=tail compl “abcde” = (5,[(0,’a’)])

get=take3 compl “abcde” = (5,[(3,’d’),(4,’e’)]) get=reverse compl “abcde” = (5,[ ])

(91)

Ein Inverses zu λs → (get s , compl s)

inv:: ([α],(Int,IntMapα))→[α]

inv (v0,(n+1,g0)) =lett = [0..n]

h =assoc (get t) v0 h0 =h++g0

in seq h (map (λi →fromJust(lookupi h0))t)

Zum Beispiel:

get=tail inv (“bcde”,(5,[(0,’a’)])) =“abcde”

get=take3 inv (“xyz”,(5,[(3,’d’),(4,’e’)])) =“xyzde”

Formal zu beweisen:

• inv (get s,compl s) =s

• wenninv (v,c)definiert, dann get(inv (v,c)) =v

• wenninv (v,c)definiert, dann compl(inv(v,c)) =c

Für den Moment, kann alszipangenommen werden.

(92)

Ein Inverses zu λs → (get s , compl s)

inv:: ([α],(Int,IntMapα))→[α]

inv (v0,(n+1,g0)) =lett = [0..n]

h =assoc (gett) v0 h0 =h++g0

in seq h (map (λi →fromJust(lookupi h0))t)

Zum Beispiel:

get=tail inv (“bcde”,(5,[(0,’a’)])) =“abcde”

get=take3 inv (“xyz”,(5,[(3,’d’),(4,’e’)])) =“xyzde”

Formal zu beweisen:

• inv (get s,compl s) =s

• wenninv (v,c) definiert, dann get(inv (v,c)) =v

• wenninv (v,c) definiert, dann compl(inv(v,c)) =c

Für den Moment, kann alszipangenommen werden.

(93)

Ein Inverses zu λs → (get s , compl s)

inv:: ([α],(Int,IntMapα))→[α]

inv (v0,(n+1,g0)) =lett = [0..n]

h =assoc (gett) v0 h0 =h++g0

in seq h (map (λi →fromJust(lookupi h0))t) Zum Beispiel:

get=tail inv (“bcde”,(5,[(0,’a’)])) =“abcde”

get=take3 inv (“xyz”,(5,[(3,’d’),(4,’e’)])) =“xyzde” Formal zu beweisen:

• inv (get s,compl s) =s

• wenninv (v,c) definiert, dann get(inv (v,c)) =v

• wenninv (v,c) definiert, dann compl(inv(v,c)) =c

Für den Moment, kann alszipangenommen werden.

(94)

Ein Inverses zu λs → (get s , compl s)

inv:: ([α],(Int,IntMapα))→[α]

inv (v0,(n+1,g0)) =lett = [0..n]

h =assoc (gett) v0 h0 =h++g0

in seq h (map (λi →fromJust(lookupi h0))t) Zum Beispiel:

get=tail inv (“bcde”,(5,[(0,’a’)])) =“abcde”

get=take3 inv (“xyz”,(5,[(3,’d’),(4,’e’)])) =“xyzde”

Formal zu beweisen:

• inv (get s,compl s) =s

• wenninv (v,c) definiert, dann get(inv (v,c)) =v

• wenninv (v,c) definiert, dann compl(inv(v,c)) =c

Für den Moment, kann alszipangenommen werden.

(95)

Ein Inverses zu λs → (get s , compl s)

inv:: ([α],(Int,IntMapα))→[α]

inv (v0,(n+1,g0)) =lett = [0..n]

h =assoc (gett) v0 h0 =h++g0

in seq h (map (λi →fromJust(lookupi h0))t) Zum Beispiel:

get=tail inv (“bcde”,(5,[(0,’a’)])) =“abcde”

get=take3 inv (“xyz”,(5,[(3,’d’),(4,’e’)])) =“xyzde”

Formal zu beweisen:

• inv (get s,compl s) =s

• wenninv (v,c) definiert, dann get(inv(v,c)) =v

• wenninv (v,c) definiert, dann compl(inv(v,c)) =c

Für den Moment, kann alszipangenommen werden.

Referenzen

ÄHNLICHE DOKUMENTE

Im Rumpf der Funktion elem wird zum einen der überladene Gleichheitsoperator verwen- det, zum anderen ruft sich die Funktion selbst rekursiv auf. Für beide Funktionsaufrufe gilt,

Geben Sie jeweils eine Gleichung für die gesuchten Bauteile R x und C x an für den Fall, dass die Abgleich- bedingung erfüllt ist.... 4.3

Auf zwei verschiedene Arten wird eine Funktion für den Temperaturverlauf hergeleitet, die für Heiß-, aber auch für Kaltgetränke gilt.. Verschiedene Fragestellungen werden geklärt,

Das Ziel der Verbesserung des Erhaltungszustandes gilt jeweils für alle bestehenden Lebensstätten von Dunklem Wiesenknopf-Ameisenbläuling, Hirschkäfer, Grünem Besenmoos , Eremit

Das Ziel der Verbesserung des Erhaltungszustandes gilt jeweils für alle bestehenden Lebensstätten von Dunklem Wiesenknopf-Ameisenbläuling, Hirschkäfer, Grünem Besenmoos , Eremit

10 Dass laut Ziel 12.1 Industrieländer „die Füh- rung“ bei der Umsetzung nachhaltiger Konsum- und Produktionsprogramme übernehmen sollen, kann und muss eine

Für die Existenz einer Wendestelle gilt folgende hinreichende Bedingung:. Eine Funktion f sei in ihrem Definitionsbereich dreimal

(2) Dass dieses Ethos nicht welt- fremd ist, weil es für Notsituationen gilt, dass in Alltagssituationen immer auch eine gehörige Portion Eigenliebe mit im Spiel ist,