summaryrefslogtreecommitdiff
path: root/edit-lens/src/Control/Lens
diff options
context:
space:
mode:
Diffstat (limited to 'edit-lens/src/Control/Lens')
-rw-r--r--edit-lens/src/Control/Lens/Edit.lhs158
1 files changed, 158 insertions, 0 deletions
diff --git a/edit-lens/src/Control/Lens/Edit.lhs b/edit-lens/src/Control/Lens/Edit.lhs
new file mode 100644
index 0000000..69a6f7f
--- /dev/null
+++ b/edit-lens/src/Control/Lens/Edit.lhs
@@ -0,0 +1,158 @@
1Ziel ist es zunächst edit-lenses alá \cite{hofmann2012edit} in Haskell zur Verfügung zu stellen.
2Dabei werden wir sowohl die Definitionen aus \cite{hofmann2012edit} sowohl in natürlicher Sprache als auch in lauffähigem Haskell vorstellen:
3
4\begin{code}
5{-# LANGUAGE TypeFamilies
6 , KindSignatures
7 , FlexibleContexts
8 , FlexibleInstances
9 , MultiParamTypeClasses
10 , FunctionalDependencies
11 , AllowAmbiguousTypes
12 , GADTs
13 #-}
14
15module Control.Lens.Edit
16 ( Module(..)
17 , StateMonoidHom
18 , HasEditLens(..)
19 , EditLens(..)
20 ) where
21\end{code}
22
23\begin{defn}[Moduln]
24Ein Modul $M$ ist eine \emph{partielle Monoidwirkung} zusammen mit einem initialen Element (bzgl. der Monoidwirkung) auf dem Träger, d.h. $M = (\Dom M, \partial M, \init_M)$ ist ein Tupel aus einer Trägermenge $\Dom M$, einem Monoid $\partial M$ zusammen mit mit einer partiellen Funktion $\cdot \colon \Dom M \times \partial M \to \Dom$, die \emph{kompatibel} ist mit der Monoid-Struktur:
25
26\begin{itemize}
27 \item $\forall m \in \Dom M \colon m \cdot 1_{\partial M} = m$
28 \item $\forall m \in \Dom M, (e, e^\prime) \in (\partial M)^2 \colon m \cdot (e e^\prime) = (m \cdot e) \cdot e^\prime$
29\end{itemize}
30
31und einem Element $\init_M \in \Dom M$, sodass gilt:
32
33$$ \forall m \in \Dom M \ \exists \partial m \in \partial M \colon m = \init_M \cdot m^\prime $$
34
35Wir führen außerdem eine Abbildung $(\init_M \cdot)^{-1} \colon \Dom M \to \partial m$ ein, die ein $m$ auf ein arbiträr gewähltes $\partial m$ abbildet für das $\init_M \cdot \partial m = m$ gilt.
36
37In Haskell charakterisieren wir Moduln über ihren Monoid, d.h. die Wahl des Monoiden \texttt{m} legt den Träger \texttt{Domain m}, die Wirkung \texttt{apply}, das initiale Element \texttt{init} und $(\init_M \cdot)^{-1}$ eindeutig fest\footnote{Betrachten wir mehrere Moduln über dem selben Träger (oder mit verschiedenen Wirkungen) führen wir neue, isomorphe, Typen ein (\texttt{newtype}-Wrappern)}.
38Eine Repräsentierung als Typklasse bietet sich an:
39
40\begin{code}
41class Monoid m => Module m where
42 type Domain m :: *
43 apply :: Domain m -> m -> Maybe (Domain m)
44 -- ^ A partial monoid-action of `m` on `Domain m`
45 --
46 -- prop> m `apply` mempty = m
47 -- prop> m `apply` (e `mappend` e') = (m `apply` e) `apply` e'
48 init :: Domain m
49 -- ^ 'init @m' (TypeApplication) is the initial element of 'm'
50 divInit :: Domain m -> Del m
51 -- ^ Calculate a representation of an element of 'Domain m' in 'Del m'
52 --
53 -- prop> init `apply` divInit m = m
54\end{code}
55\end{defn}
56
57Wir weichen von der originalen Definition von Moduln aus \cite{hofmann2012edit} darin ab, dass wir für das ausgezeichnete Element $\init_X$ des Trägers explizit (und konstruktiv) fordern, dass es ein initiales Element bzgl. der Monoidwirkung sei.
58
59\begin{comment}
60\begin{defn}[Modulhomomorphismen]
61Unter einem Modulhomomorphismus zwischen Moduln $M$ und $M^\prime$ verstehen wir ein Paar $(f, \phi$) bestehend aus Abbildungen $f \colon \Dom M \to \Dom M^\prime$ und $\phi \colon \partial M \to \partial M^\prime$, sodass gilt:
62\begin{itemize}
63 \item $\phi$ ist ein Monoidhomomorphismus:
64
65 \begin{itemize}
66 \item $\phi(1_{\partial M}) = 1_{\partial M^\prime}$
67 \item $\forall (e, e^\prime) \in (\partial M)^2 \colon \phi(e e^\prime) = \phi(e) \phi(e^\prime)$
68 \end{itemize}
69 \item $f$ erhält das initiale Element:
70
71 $$f(\init_M) = \init_N$$
72 \item $f$ und $\phi$ sind \emph{kompatibel}:
73
74 $$\forall m \in \Dom M, e \in \partial M \colon f(m \cdot e) = f(m) \cdot \phi(e)$$
75\end{itemize}
76
77\begin{code}
78{-
79data ModuleHom m n where
80 ModuleHom :: (Module m, Module n) => (Domain m -> Domain n) -> (m -> n) -> ModuleHom m n
81-}
82\end{code}
83\end{defn}
84\end{comment}
85
86\begin{defn}[Zustandsbehaftete Monoidhomomorphismen]
87Mit einer Menge von Komplementen $C$ und Monoiden $M$ und $N$ nennen wir eine partielle Funktion $\psi \colon C \times M \to C \times N$ einen zustandsbehafteten Monoidhomomorphismus wenn sie den folgenden Ansprüchen genügt:
88
89\begin{itemize}
90 \item $\forall c \in C \colon \psi(1_M, c) = (1_N, c)$
91 \item Mit $\psi(m, c) = (n, c^\prime)$ und $\psi(m^\prime, c^\prime) = (n^\prime, c^{\prime \prime})$:
92
93 $$\psi(m m^\prime, c) = (n n^\prime, c^{\prime \prime})$$
94\end{itemize}
95
96\begin{code}
97-- | A stateful monoid homomorphism
98type StateMonoidHom s m n = (s, m) -> (s, n)
99\end{code}
100\end{defn}
101
102\begin{defn}[edit-lenses]
103Für Moduln $M$ und $N$ besteht eine symmetrische edit-lens zwischen $M$ und $N$ aus zwei zustandsbehafteten Monoidhomomorphismen $\Rrightarrow \colon C \times \partial M \to C \times \partial N$ und $\Lleftarrow \colon C \time \partial N \to C \times \partial M$, mit kompatiblem Komplement $C$, einem ausgezeichneten Element $\ground_C$ und einer \emph{Konsistenzrelation} $K \subset \Dom M \times C \times \Dom N$ sodass gilt:
104
105\begin{itemize}
106 \item $(\init_M, \ground_C, \init_N) \in K$
107 \item Für beliebige $m \in \Dom M, n \in \Dom n, \partial m \in \partial M, \partial n \in \partial N, c \in C$ folgt, wenn $m \cdot \partial m$ definiert ist und $\Rrightarrow(c, \partial m) = (c, \partial n)$ gilt:
108
109 \begin{itemize}
110 \item $n \cdot \partial n$ ist ebenfalls definiert
111 \item $(m \cdot \partial m, c^\prime, n \cdot \partial n) \in K$
112 \end{itemize}
113 \item Analog für $\Lleftarrow$
114\end{itemize}
115
116Wir schreiben auch nur \emph{edit-lens} für den symmetrischen Fall\footnote{Für den asymmetrischen Fall siehe \cite{johnson2016unifying}}.
117
118In Haskell erwähnen wir die Konsistenzrelation nicht in der Erwartung, dass $\Rrightarrow$ und $\Lleftarrow$ nur auf konsistente Zustände angewandt werden (und somit auch entweder einen konsistenten Zustand erzeugen oder nichtt definiert sind):
119
120\begin{code}
121data EditLens c m n where
122 EditLens :: (Module m, Module n) => c -> StateMonoidHom c m n -> StateMonoidHom c n m -> EditLens c m n
123
124class (Module m, Module n) => HasEditLens l m n | l -> m, l -> n where
125 type Complement l :: *
126 ground :: l -> Complement l
127 -- ^ A default state from 'Complement l'
128 propR :: l -> StateMonoidHom (Complement l) m n
129 -- ^ Map edits of 'm' to changes of 'n', maintaining some state from 'Complement l'
130 propL :: l -> StateMonoidHom (Complement l) n m
131 -- ^ Map edits of 'n' to changes of 'm', maintaining some state from 'Complement l'
132
133-- | Inspect the components of an edit lens (e.g. 'EditLens')
134instance HasEditLens (EditLens c m n) where
135 type Complement (EditLens c m n) = c
136 ground (EditLens g _ _) = g
137 propR (EditLens _ r _) = r
138 propL (EditLens _ _ l) = l
139\end{code}
140\end{defn}
141
142\paragraph{Kompatibilität mit bestehenden lens frameworks}
143
144Das einschlägige bestehende lens framework \cite{lens} konstruiert seine Linsen alá \citeauthor{laarhoven} wie folgt:
145
146\begin{defn}[lenses alá \citeauthor{laarhoven}]
147Für Typen $n$ und $m$ ist eine \emph{lens} $\ell$ von $n$ in $m$ eine Abbildung\footnote{Gdw. die betrachtete Linse einen Isomorphismus kodiert wird auch über den verwendeten Profunktor anstatt $\to$ quantifiziert} folgender Struktur:
148
149$$ \forall f \, \text{Funktor} \colon \left ( \ell \colon \left ( m \to f(m) \right ) \to \left ( n \to f(n) \right ) \right )$$
150
151Durch geschickte Wahl des Funktors\footnote{\texttt{Const} bzw. \texttt{Identity}} $f$ können dann $\searrow \colon m \to n$ und $\nearrow \colon (m \to m) \to (n \to n)$ rekonstruiert werden oder verwandte Strukturen (folds, traversals, …) konstruiert werden.
152\end{defn}
153
154Es liegt nun nahe $\nearrow \colon (m \to m) \to (n \to n)$ mit $\Rrightarrow \colon \partial m \to \partial n$ zu identifizieren.
155Und in der Tat, eine Funktion $\text{map} \colon (o \to o) \to \partial o$ für $o \in \{ m, n \}$ würde van Laarhoven-lenses in edit-lenses einbetten.
156Die charakteristische Eigenschaft der Betrachtung als edit-lens, nämlich die algebraische Struktur von $\partial o$, würde hierbei jedoch notwendigerweise verloren gehen.
157
158Wegen diesem Argument haben wir entschieden keine Komponierbarkeit (durch $\text{id} \colon a \to a$ und $\circ \colon (b \to c) \to (a \to b) \to (a \to c)$, wie in \cite{lens}) von edit-lenses mit van Laarhoven-lenses anzustreben.