X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;ds=sidebyside;f=appendix%2Fclean_for_haskell_programmers.tex;h=65dfb876da6052c5ccf300b47a499988da99c4da;hb=c15776f71f5efe186708e2604ff8f32115c8ac3d;hp=715964c506fe5456e2076286e87876173666731e;hpb=c6fa9017e897e847334aeee2cec0b9aadec6f7c5;p=phd-thesis.git diff --git a/appendix/clean_for_haskell_programmers.tex b/appendix/clean_for_haskell_programmers.tex index 715964c..65dfb87 100644 --- a/appendix/clean_for_haskell_programmers.tex +++ b/appendix/clean_for_haskell_programmers.tex @@ -1,5 +1,25 @@ +\documentclass[../thesis.tex]{subfiles} + +\begin{document} + +\ifSubfilesClassLoaded{ + \pagenumbering{arabic} +}{ +} + +\chapter{\texorpdfstring{\glsentrytext{CLEAN}}{Clean} for \texorpdfstring{\glsentrytext{HASKELL}}{Haskell} Programmers}% +\label{chp:clean_for_haskell_programmers} + +This note is meant to give people who are familiar with the functional programming language \gls{HASKELL} a consise overview of \gls{CLEAN} language elements and how they differ from \gls{HASKELL}. +The goal is to support the reader when reading \gls{CLEAN} code. +Table~\ref{tbl:syn_clean_haskell} shows frequently occuring \gls{CLEAN} language elements on the left side and their \gls{HASKELL} equivalent on the right side. +Obviously, this summary is not exhaustive. +Some \gls{CLEAN} language elements that are not easily translatable to \gls{HASKELL} and thus do not occur in the summary following below. +We hope you enjoy these notes and that it aids you in reading \gls{CLEAN} programs. + While \gls{CLEAN} and \gls{HASKELL} were both conceived around 1987 and have similar syntax, there are some subtle differences in syntax and functionality. -This section describes some of the history of \gls{CLEAN} and provides a crash course in \gls{CLEAN} pecularities writen for \gls{HASKELL} programmers. +This section describes some of the history of \gls{CLEAN} and provides a crash course in \gls{CLEAN} pecularities written for \gls{HASKELL} programmers. +It is based on the \Gls{CLEAN}---acronym for Clean \acrlong{LEAN}~\cite{barendregt_towards_1987}---, was originally designed as a \gls{GRS} core language but quickly served as an intermediate language for other functional languages~\cite{brus_clean_1987}. In the early days it has also been called \emph{Concurrent} \gls{CLEAN}~\cite{nocker_concurrent_1991} but these days the language has no support for this anymore. @@ -10,7 +30,7 @@ However, over the years, the syntax got friendlier and it currently it looks a l In the past, a \emph{double-edged} fronted even existed that allowed \gls{CLEAN} to be extended with \gls{HASKELL98} syntax and vice versa, however this frontend is no longer maintained~\cite{groningen_exchanging_2010}. This chapter therefore gives a brief syntactical and functional comparison, a complete specification of the \gls{CLEAN} language can be found in the latest language report~\cite{plasmeijer_clean_2021}. Many of this is based on work by Achten although that was based on \gls{CLEAN} 2.1 and \gls{HASKELL98}~\cite{achten_clean_2007}. -When \gls{HASKELL} is mentioned I actually mean \gls{GHC}'s \gls{HASKELL} and by \gls{CLEAN} I mean \gls{CLEAN} 3.1's \gls{ITASK} compiler. +When \gls{HASKELL} is mentioned we actually mean \gls{GHC}'s \gls{HASKELL}\footnote{If an extension is enabled, a footnote is added stating that \GHCmod{SomeExtension} is required.} this is denoted and by \gls{CLEAN} we mean \gls{CLEAN} 3.1's compiler with the \gls{ITASK} extensions. \section{Features} \subsection{Modules} @@ -23,17 +43,17 @@ Choosing what is exported in \gls{HASKELL} is done using the \haskellinline{modu \subsection{Strictness} In \gls{CLEAN}, by default, all expressions are evaluated lazily. -Types can be annotated with a strictness attribute (\cleaninline{!}), resulting in the values being evaluated to head-normal form before the function is entered. +Types can be annotated with a strictness attributes (\cleaninline{!}), resulting in the values being evaluated to head-normal form before the function is entered. In \gls{HASKELL}, in patterns, strictness can be enforced using \haskellinline{!}\requiresGHCmod{BangPatterns}. Within functions the strict let (\cleaninline{#!}) can be used to force evaluate an expression, in \gls{HASKELL} \haskellinline{seq} or \haskellinline{\$!} is used for this. \subsection{Uniqueness typing} -Types in \gls{CLEAN} may be \emph{unique}, which means that they may not be shared\todo{cite}. +Types in \gls{CLEAN} may be \emph{unique}, which means that they may not be shared~\cite{barendsen_uniqueness_1996}. The uniqueness type system allows the compiler to generate efficient code because unique data structures can be destructively updated. -Furthermore, uniqueness typing serves as a model for side effects as well. -\Gls{CLEAN} uses the \emph{world-as-value} paradigm where \cleaninline{World} represents the external environment and is always unique. +Furthermore, uniqueness typing serves as a model for side effects as well~\cite{achten_high_1993,achten_ins_1995}. +\Gls{CLEAN} uses the \emph{world-as-value} paradigm where \cleaninline{World} represents the external environment and is always unique~\cite{backus_introduction_1990}. A program with side effects is characterised by a \cleaninline{Start :: *World -> *World} start function. -In \gls{HASKELL}, interaction with the world is done using the \haskellinline{IO} monad. +In \gls{HASKELL}, interaction with the world is done using the \haskellinline{IO} monad~\cite{peyton_jones_imperative_1993}. The \haskellinline{IO} monad could very well be---and actually is---implemented in \gls{CLEAN} using a state monad with the \cleaninline{World} as a state. Besides marking types as unique, it is also possible to mark them with uniqueness attributes variables \cleaninline{u:} and define constraints on them. For example, to make sure that an argument of a function is at least as unique as another argument. @@ -41,7 +61,7 @@ Finally, using \cleaninline{.} (a dot), it is possible to state that several var Uniqueness is propagated automatically in function types but must be marked manually in data types. Examples can be seen in \cref{lst:unique_examples}. -\begin{lstClean}[label={lst:unique_examples},caption={Examples of uniqueness annotations}] +\begin{lstClean}[label={lst:unique_examples},caption={Examples of uniqueness annotations.}] f :: *a -> *a // f works on unique values only f :: .a -> .a // f works on unique and non-unique values f :: v:a u:b -> u:b, [v<=u] // f works when a is less unique than b @@ -51,22 +71,46 @@ f :: v:a u:b -> u:b, [v<=u] // f works when a is less unique than b %:: T = T (Int -> *(*World -> *World)) // Writing :: T = T (Int *World -> *World) won't work \subsection{Expressions} -\todo[inline]{Matches pattern expression \texttt{=:}} +Patterns in \gls{CLEAN} can be used as predicates as well~\cite[Chp.~3.4.3]{plasmeijer_clean_2021}. +Using the \cleaninline{=:} operator, a value can be tested against a pattern. +Variable names are not allowed but wildcard patterns \cleaninline{\_} are. + +\begin{lstClean}[label={lst:matches_pattern_expression},caption={Examples of \emph{matches pattern} expressions.}] +isNil :: [a] -> Bool +isNil l = l=:[] -\todo[inline]{Let before} +:: T = A Int | B Bool + +ifAB :: T a a -> a +ifAB x ifa ifb = if (x =: (A _)) ifa ifb +\end{lstClean} + +Due to the nature of uniqueness typing, many functions in \gls{CLEAN} are state transition functions with possibly unique states. +The \emph{let before} construct allows the programmer to specify sequential actions without having to invent unique names for the different versions of the state. +\Cref{lst:let_before} shows an example of the usage of the \emph{let before} construct (adapted from~\cite[Chp.~3.5.4]{plasmeijer_clean_2021}). + +\begin{lstClean}[label={lst:let_before},caption={Let before expression example.}] +readChars :: *File -> ([Char], *File) +readChars file +# (ok, char, file) = freadc file +| not ok = ([], file) +# (chars, file) = readChars file += ([char:chars], file) +\end{lstClean} \subsection{Generics} Polytypic functions~\cite{jeuring_polytypic_1996}---also known as generic or kind-indexed fuctions---are built into \gls{CLEAN}~\cite[Chp.~7.1]{plasmeijer_clean_2021}\cite{alimarine_generic_2005} whereas in \gls{HASKELL} they are implemented as a library~\cite[Chp.~6.19.1]{ghc_team_ghc_2021}. +The implementation of generics in \gls{CLEAN} is very similar to that of Generic H$\forall$skell~\cite{hinze_generic_2003}. %When calling a generic function, the kind must always be specified and depending on the kind, the function may require more arguments. For example, defining a generic equality is done as in \cref{lst:generic_eq}. \lstinputlisting[language=Clean,firstline=4,label={lst:generic_eq},caption={Generic equality function in \gls{CLEAN}.}.]{lst/generic_eq.icl} -Metadata about the types is available using the \cleaninline{of} syntax that gives the function access to metadata records, as can be seen in \cref{lst:generic_print} showing a generic print function. This abundance of metadata allows for very complex generic functions that near the expression level of template metaprogramming\todo[inline]{crossref chapter c-code generation}. +Metadata about the types is available using the \cleaninline{of} syntax that gives the function access to metadata records, as can be seen in \cref{lst:generic_print} showing a generic print function. This abundance of metadata allows for very complex generic functions that near the expression level of template metaprogramming\ifSubfilesClassLoaded{}{ (See \cref{chp:first-class_datatypes})}. \lstinputlisting[language=Clean,firstline=4,label={lst:generic_print},caption={Generic print function in \gls{CLEAN}.}]{lst/generic_print.icl} -\subsection{\glsentrytext{GADT}s} -GADTs are enriched data types that allow the type instantiation of the constructor to be explicitly defined~\cite{cheney_first-class_2003,hinze_fun_2003}. +\subsection{\texorpdfstring{\glsentrytext{GADT}}{GADT}s} +\Glspl{GADT} are enriched data types that allow the type instantiation of the constructor to be explicitly defined~\cite{cheney_first-class_2003,hinze_fun_2003}. While \glspl{GADT} are not natively supported in \gls{CLEAN}, they can be simulated using embedding-projection pairs or equivalence types~\cite[Sec.~2.2]{cheney_lightweight_2002}. To illustrate this, \cref{lst:gadt_clean} shows an example \gls{GADT} that would be implemented in \gls{HASKELL} as done in \cref{lst:gadt_haskell}\requiresGHCmod{GADTs}. @@ -107,9 +151,9 @@ To illustrate this, \cref{lst:gadt_clean} shows an example \gls{GADT} that would \cleaninline{True :: Bool} & \haskellinline{True :: Bool}\\ \cleaninline{toInteger 42 :: Integer} & \haskellinline{42 :: Integer}\\ \cleaninline{38.0 :: Real} & \haskellinline{38.0 :: Float -- or Double}\\ - \cleaninline{"Hello" +++ "World" :: String}\footnote{Strings are represented as unboxed character arrays.} - & \haskellinline{"Hello" ++ "World" :: String}\footnote{Strings are represented as lists of characters by default but may be overloaded as well if \GHCmod{OverloadedStrings} is enabled.}\\ - \cleaninline{['Hello'] :: [Char]} & \haskellinline{"Hello" :: String}\\ + \cleaninline{\"Hello\" +++ \"World\" :: String}\footnote{Strings are represented as unboxed character arrays.} + & \haskellinline{\"Hello\" ++ \"World\" :: String}\footnote{Strings are represented as lists of characters by default but may be overloaded as well if \GHCmod{OverloadedStrings} is enabled.}\\ + \cleaninline{['Hello'] :: [Char]} & \haskellinline{\"Hello\" :: String}\\ \cleaninline{?t} & \haskellinline{Maybe t}\\ \cleaninline{(?None, ?Just e)} & \haskellinline{(Nothing, Just e)}\\ @@ -122,7 +166,7 @@ To illustrate this, \cref{lst:gadt_clean} shows an example \gls{GADT} that would \cleaninline{:: T a0 ...} & \haskellinline{data T a0 ...}\\ \quad\cleaninline{= \{ f0 :: t0, ..., fn :: tn \} } & \quad\haskellinline{= T \{ f0 :: t0, ..., fn :: tn \} }\\ \cleaninline{:: T a0 ... =: t} & \haskellinline{newtype T a0 ... = t}\\ - \cleaninline{:: T = E.t Box t \& C t} & \haskellinline{data T = forall t.C t => Box t}\requiresGHCmod{ExistentialQuantification}\\ + \cleaninline{:: T = E.t: Box t \& C t} & \haskellinline{data T = forall t.C t => Box t}\requiresGHCmod{ExistentialQuantification}\\ \midrule \multicolumn{2}{c}{Function types}\\ @@ -220,3 +264,5 @@ To illustrate this, \cref{lst:gadt_clean} shows an example \gls{GADT} that would \bottomrule \end{longtable} +\input{subfilepostamble} +\end{document}