A concise guide for anyone that's met with the terrible fate of having to program in Clean (so mainly for Radboud University students).
%-------------------------------LATEX SYNTAX----------------------------------
%
% enter: \\, \linebreak, \newline
% new page: \newpage
% tab: \tab
% new section: \section{name} text
% new paragraph \subsection{name} text (subsub...section{name} for more layers)
% refer: \nameref{label name} (place "\label{name}" at the position you want to refer to)
% %, &, $, etc: \%, \&, \$, etc (these are latex operators, add a "\" to type it as text)
% add comment: \commred{text}, \commblue{text}, \commpurp{text}, \commgreen{text}
% bullet points: \begin{itemize} \item{text} ... \item{text} \end{itemize}
% clean code: \cleancode{text}
% idem without indent:\cleanstyle{text}
% bold, italic, under:\textbf{text}, textit{text}, \underline{text}
% table: \begin{tabular}{c c c} text \end{tabular} ('&' for tab, '\\' for new line)
%
% use Google for the rest
%
%------------------------------------------------------------------------------
\documentclass[a4paper]{article}
\usepackage[utf8x]{inputenc}
\usepackage[british,UKenglish]{babel}
\usepackage{amsmath}
%\usepackage{titlesec}
\usepackage{color}
\usepackage{graphicx}
\usepackage{fancyref}
\usepackage{hyperref}
\usepackage{float}
\usepackage{scrextend}
\usepackage{setspace}
\usepackage{xargs}
\usepackage{multicol}
\usepackage{nameref}
\usepackage[pdftex,dvipsnames]{xcolor}
\usepackage{sectsty}
\graphicspath{ {images/} }
\newcommand\tab[1][1cm]{\hspace*{#1}}
\hypersetup{colorlinks=true, linkcolor=black}
\interfootnotelinepenalty=10000
%\titleformat*{\subsubsection}{\large\bfseries}
\subsubsectionfont{\large}
\subsectionfont{\Large}
\sectionfont{\LARGE}
\definecolor{cleanOrange}{HTML}{D14D00}
\definecolor{cleanYellow}{HTML}{FFFF99}
\definecolor{cleanBlue}{HTML}{3d0099}
%\newcommand{\cleancode}[1]{\begin{addmargin}[3em]{3em}\fcolorbox{cleanOrange}{cleanYellow}{\texttt{\textcolor{cleanOrange}{#1}}}\end{addmargin}}
\newcommand{\cleancode}[1]{\begin{addmargin}[3em]{3em}\texttt{\textcolor{cleanOrange}{#1}}\end{addmargin}}
\newcommand{\cleanstyle}[1]{\text{\textcolor{cleanOrange}{\texttt{#1}}}}
\usepackage[colorinlistoftodos,prependcaption,textsize=footnotesize]{todonotes}
\newcommandx{\commred}[2][1=]{\textcolor{Red}
{\todo[linecolor=red,backgroundcolor=red!25,bordercolor=red,#1]{#2}}}
\newcommandx{\commblue}[2][1=]{\textcolor{Blue}
{\todo[linecolor=blue,backgroundcolor=blue!25,bordercolor=blue,#1]{#2}}}
\newcommandx{\commgreen}[2][1=]{\textcolor{OliveGreen}{\todo[linecolor=OliveGreen,backgroundcolor=OliveGreen!25,bordercolor=OliveGreen,#1]{#2}}}
\newcommandx{\commpurp}[2][1=]{\textcolor{Plum}{\todo[linecolor=Plum,backgroundcolor=Plum!25,bordercolor=Plum,#1]{#2}}}
%-----------------------------------------BEGIN DOC----------------------------------------
\begin{document}
\title{{\Huge Clean more like\\ I wanna clill myself{\large\linebreak\\}}{\Large A guide to programming in Clean
\\\textit{without} the suicidal tendencies.\linebreak\linebreak}
\linebreak{\Huge[\nameref{c}]}
\linebreak{\small click on it\linebreak}}
\author{\\Authors: Melle P. Starke \& Crippling D. Pression\\\\
1617 Functional Programming for Artificial Intelligence Students\\
(NWI-IBC015-2016-KW3-V)\\\\
Radboud University, Netherlands\\
Faculty of Social Sciences\\
Artificial Intelligence}
\date{27 March 2017}
\maketitle
\newpage
%-----------------------------------------ABSTRACT-------------------------------------
{\large\bf{"SWEET JEZUS WHY!?"\\}}
\begin{addmargin}[2em]{2em}{\setstretch{0.6}{\small\textit{If you're reading this, chances are that either your arms are suffering from anemia from waiting for the TA's to finish helping the 20 people in the room, or you're trying to program in Clean without any TA's whatsoever, and you just wanna end it all. Fret not! This document serves as an encyclopedia for basic explanations of clean code and datatypes, helpful links and forbidden coding secrets whose names none dare speak.}}}
\end{addmargin}
\tableofcontents\label{c}
\newpage
%------------------------------------------TEXT--------------------------------------------
%----------------------------------------INTERFACE-----------------------------------------
\section{Things Everyone Should Know} \label{Things Everyone Should Know}%------------------------------
Clean can be quite confusing and illogical, so here's some tips on how to get around this dumpster fire:
\begin{itemize}
\item{\textbf{In order to work on a project}, the .prj file, the .icl file (this is where you'll be coding in) and the .dlc file need to be accessible by clean.}
\item{\textbf{When wanting to run an .icl file} you first need to load the .prj file.}
\item{\textbf{You can only have one .prj file open at a time}, but you can have multiple .icl files open.}
\item{\textbf{The .icl file can be loaded by opening the .prj file} and double-clicking it in the light brown coloured project window.}
\item{\textbf{You can open de .dcl file} by pressing Ctrl + / (also works the other way around).}
\item{\textbf{If you don't know what a certain type or function does,} you can look it up by Ctrl + double-clicking it.}
\item{\textbf{If you disable a function in the .icl file} by commenting it out ("//"), you might need to do the same thing in the .dcl file.}
\item{\textbf{You can comment multiple lines} by putting "/*" at the top and "*/" at the bottom.}
\item{\textbf{Disable "info" in the pink "Errors \& Warnings" window.} It'll only scare you.}
\item{\textbf{Clean's Ctrl+Z command initially only stores one change at a time.} But apparently there is a way to fix it. If you do delete your entire code and can't get it back, just load the .icl file again, there's no autosave.}
\item{\textbf{You can add line numbers} by going to Defaults $\rightarrow$ Window Settings $\rightarrow$ Editor Settings $\rightarrow$ Show LineNrs.}
\item{\textbf{There's a lot of helpful commands in Clean's standard environment} (StdEnv). Seriously, if you're stuck, check the StdEnv section in Functional Programming in Clean first (see \underline{\nameref{Helpful Links}}).}
\item{\textbf{You can close the .exe file by pressing any key.} Keeping it open will prevent you from running the code.}
\item In clean, \textbf{\cleanstyle{::} is always used to assign types, and \cleanstyle{=} is always used to assign values.}
\item \textbf{If you can't find something in this guide} look for it in \underline{\nameref{Helpful Links}} or just Google the Haskell code, it has really similar syntax.
\end{itemize}
%-----------------------------------------SYNTAX-------------------------------------------
\newpage
\section{Syntax} \label{Syntax}%------------------------------
\subsection{Differences Compared to Java} \label{Differences Compared to Java}%----------
Clean is a functional programming language. This means it needs to execute code in "one line". Code such as\\
\cleancode{if(raining)\{\\\tab getCoat(waterProof);\\\tab getUmbrella();\\\}\\}
won't work. You cannot group commands together. Because of this, you also cannot easily save some of your values, then come up with the next step, it all needs to be done in \textit{one} step.
\\\\
Clean does not have while-loops or for-loops. Instead, you use recursion when you need to loop something.
It also does not show syntax errors in real-time, you have to bring it up to date (Ctrl+U) in order to see the errors.
And whereas Java functions can only return a single value, Clean functions can return multiple, if written as \underline{\nameref{Tuple}}.
In Clean, parameters are passed to functions with spaces. If a function needs 2 arguments, it's just gonna look for the next 2 things separated by spaces. But you can group things together by using parentheses. In Clean, parentheses are used to group things together, rather than to pass parameters. Which is more like a math kind of approach.
\subsection{Operators} \label{Operators}%------------------------------
Clean operators are rather similar to Java operators, but since there are quite a few differences, here's a list of 'em. Any operator that isn't in this list is just the same as in Java.\\
\begin{tabular}{ c c c }
\cleanstyle{Operator}&\cleanstyle{Output}&\cleanstyle{Meaning}\\
\hline
\cleanstyle{zero}&\cleanstyle{Assign}&\cleanstyle{zero value of datatype}\\
\cleanstyle{one}&\cleanstyle{Assign}&\cleanstyle{one value of datatype}\\
\cleanstyle{x +++ y}&\cleanstyle{String}&\cleanstyle{"add string x to string y"}\\
\cleanstyle{x ++ y}&\cleanstyle{List}&\cleanstyle{"add list x to list y}\\
\cleanstyle{x\^{}y}&\cleanstyle{Int/Real}&\cleanstyle{"x to the power y"}\\
\cleanstyle{{\raise.17ex\hbox{$\scriptstyle\sim$}}x}&\cleanstyle{Int/Real}&\cleanstyle{"switch sign of x" (+ / -)}\\
\cleanstyle{xs \% (x,y)}&\cleanstyle{String/List}&\cleanstyle{slice from index x to index y of xs}\\
\cleanstyle{x rem y}&\cleanstyle{Int/Real}&\cleanstyle{modulo (remainder of a division)}\\
\end{tabular}\linebreak\linebreak\linebreak
Note: \cleanstyle{zero} and \cleanstyle{one} assign a value to a certain type and can be used on all basic types. \cleanstyle{zero :: Int = 0}, for example. And \cleanstyle{zero :: Real = 0.0}.
%---------------------------------------DATATYPES------------------------------------------
\newpage
\section{Datatypes} \label{Datatypes}%------------------------------
\subsection{Basic Types} \label{Basic Types}%------------------------------
Clean does not have all the same basic datatypes as Java. So here's a list:\\
\begin{tabular}{ c c c }
\cleanstyle{Name}&\cleanstyle{Meaning}&\cleanstyle{zero value}\\
\hline
\cleanstyle{Int}&\cleanstyle{Whole Number}&\cleanstyle{0}\\
\cleanstyle{Real}&\cleanstyle{Decimal Number}&\cleanstyle{0.0}\\
\cleanstyle{Bool}&\cleanstyle{Boolean}&\cleanstyle{}\\
\cleanstyle{Char}&\cleanstyle{Character}&\cleanstyle{''}\\
\cleanstyle{String}&\cleanstyle{String}&\cleanstyle{""}\\
\hline
\cleanstyle{a}&\cleanstyle{Any Type}&\cleanstyle{}\\
\end{tabular}\linebreak\linebreak\linebreak
NOTE: \cleanstyle{a} is used in function input \& output declaration, and can be any letter. If you use different letters in your function definition, it means that they need to be different types.
\subsection{Algebraic Type} \label{Algebraic Type}%------------------------------
An algebraic type is simply an entirely new type, with a certain amount of possible values (so not a data structure like tuples or record types). If you know what an enumeration is in Java, it's basically that. Every basic type in Clean is an algebraic type. The definition of \cleanstyle{Bool}, for example, looks like this:\\
\cleancode{
:: Bool = True | False\\
}With the possible values (here known as \textit{data constructors}) separated by guards.\\\\
If you make a new algebraic type, you can of course use it in your code:\\
\cleancode{ :: Day = Mon Tue | Wed | Thu | Fri | Sat | Sun \\\\isWeekend :: Day -> Bool\\
isWeekend Sat = True\\
isWeekend Sub = True\\
isWeekend \_ = False\\}This also means that \cleanstyle{Sat :: Day}.
\\\\
Apart from being separate values for \cleanstyle{Day}, they're nothing more. They're not linked to their positions and so cannot be called with a number. \cleanstyle{Day} is just a new type that can have 7 separate values. If you do want to link their values to certain positions, just make a list and put all the values in there in a certain order, then use \cleanstyle{hd}, \cleanstyle{tl} and \cleanstyle{[x:xs]} to go through the elements.
\\\\
Also, any value can only be of one type. Which means that \cleanstyle{:: Weekend = Sat | Sun} and \cleanstyle{:: Dice = 1 | 2 | 3 | 4 | 5 | 6} will result in an error. Also for some reason, values of a new algebraic type need to begin with a capital letter.
\subsection{Data Structures} \label{Data Structure}%---------------------------
\subsubsection{Tuples} \label{Tuple}%------------------------------
A tuple is a type that consist of multiple types. There's different kinds of tuples, like a double: (Rain,Sun) and a triple: (1,7,3). Note that singles don't exist, a (7) is just read as an \cleanstyle{Int}.
\\\\
The types within a tuple can be anything (even another tuple) and can be different from each other. For example, \cleanstyle{(("Rain","Sun"),1,'k',Contains)} is a valid quadruple, with type \cleanstyle{((String, String), Int, Char, (Char String -> Bool))}, in that order.
\\\\
Tuples can be used to make a function have multiple outputs by just writing the output as a tuple. Ex:\\ \cleancode{
toDouble :: a a -> (a,a)\\
toDouble x y = (x,y)\\}
NOTE: The order of the elements in a tuple is highly important.
Each tuple\\\tab[1.3cm]with a certain order and amount of types is a distinct type of its own.
\\\\
Defining a new tuple in Clean looks like this:\\
\cleancode{
Tuple1 :: ((String,String),Int,Char)\\
Tuple2 :: (Bool,Real,Char String->Bool)\\
}
NOTE: Tuples don't always have to be defined. \cleanstyle{Start = (1,7,3)} is perfectly\\\tab[1.3cm]fine. But sometimes it can be helpful to define a tuple. And when\\\tab[1.3cm]writing a function definition that uses a tuple it's of course necessary\\\tab[1.3cm]to define the type of the tuple.
\subsubsection{Record Types} \label{Record Type}%------------------------------
A record type is a type consisting of multiple types. Record types can contain different sorts of types, much like \underline{\nameref{Tuple}}. But unlike tuples, the order of the elements is irrelevant (even when defining and constructing the record type). This is because you name each element (a bit like object oriented programming in Java):\\
\cleancode{
\commgreen{:: signifies new type}:: Person = \{ name :: String\\
\tab[2.45cm]\commred{"name :: type", separated by commas}, birthdate :: (Int,Int,Int)\\
\tab[2.45cm], parents :: (Person,Person)\\\tab[2.45cm]\commpurp{\} signifies record type}\}
}
NOTE: This can be written in one line as well, but this way comments look\\\tab[1.3cm]better (And for some reason elements of a record type need to begin
\\\tab[1.3cm]with a lower case letter).\\\\
This is only the definition of the new record type \cleanstyle{Person}. It does not contain any values yet. In order to make a new \cleanstyle{Person}, you have to give it a name and assign values to it:\\
\cleancode{\commblue{define Bert as type Person}Bert :: Person\\
Bert = \{ name = Bert\\
\tab[1.3cm], \commred{notice similar structure. But with = instead of ::}parents = (Jochem,Greta)\\
\tab[1.3cm], birthdate = (30,2,1989)\\\tab[1.3cm]\}\\\\}
\textbf{Getting Record Type Values\\\\}
When wanting an element of a record type, you generally use dots (much like in Java when you want a value or function of an object).\\
\cleancode{
:: Birthdate = \{day :: Int, month :: Int, year :: Int\}
\\\\
getYear :: Birthdate -> Int\\
getYear x = x.year\\}
The above function returns the element \cleanstyle{year} of the record type \cleanstyle{Birthdate}. As for an example:\\
\cleancode{
CuriousBetsy's :: Birthdate\\
CuriousBetsy's = \{Day = 2, month = 2, year = 1984\}\\
Start = getYear CuriousBetsy's\\
}This
function
will have as output \cleanstyle{1984}.
\\\\
Record types can be passed in 2 ways. with a dot, or with curly brackets. The function \cleanstyle{getYear} might just as well have been \cleanstyle{getYear \{year\} = year}. In the latter case you don't need to pass all the elements, just the ones you need. If you do need more you can separate them with commas.
\subsubsection{Lists} \label{Lists}%------------------------------
Lists, like tuples, are data structures with elements on certain positions. But unlike tuples, a list can contain zero or more elements and can only contain elements of the same type.\\\\
There are a few ways to write the contents of a list:\\
\begin{tabular}{l l}
canonical:&\cleanstyle{[1:[2:[3:[]]]]}\\
shorthand canonical&\cleanstyle{[1:2:3[]]}\\
plain&\cleanstyle{[1,2,3]}\\
enumeration&\cleanstyle{[1..3]}\\
\end{tabular}\linebreak\linebreak\linebreak
The last one is more of a way to make a list. This particular one creates a list of all numbers between and including 1 and 3, with intervals of 1. So: \cleanstyle{[1,2,3]}. You can change the interval of an enumeration by specifying the 2nd element. It'll enumerate all numbers between and including the 1st and last number, with intervals of the 2nd number minus the 1st. So \cleanstyle{[1,3..9]} = \cleanstyle{[1,3,5,7,9]}. If the last number is not in the list, it'll go up to the last included element before that. So \cleanstyle{[1,3..10]} = \cleanstyle{[1,3,5,7,9]}. And infinite lists are also possible: \cleanstyle{[1..]}.\\\\There's a few symbols that you can use for lists in pattern definitions:\\
\begin{tabular}{c c c}
\cleanstyle{Symbol}&\cleanstyle{Example}&\cleanstyle{Meaning}\\
\hline
\cleanstyle{:}&\cleanstyle{[x:xs]}&\cleanstyle{splits head (1st element (x))}\\&&\cleanstyle{from tail (the rest (xs))}\\
\cleanstyle{,}&\cleanstyle{[x,y,z:xs]}&\cleanstyle{"these consecutive elements"}\\
\cleanstyle{\textunderscore}&\cleanstyle{[x:\textunderscore]}&\cleanstyle{"I don't care what this is"}\\
\cleanstyle{[]}&\cleanstyle{[x:[]]}&\cleanstyle{empty list}\\
\end{tabular}\linebreak\linebreak\linebreak
This also means that a list with one element can be written as \cleanstyle{[x:[]]}. Also note that in the case of \cleanstyle{[x:xs]} and \cleanstyle{[x:\textunderscore]}, both tails can be empty.\\
\\\textbf{{\large Subsetting a List}}
\\\\
Apparently there's functions for lists that you can use to get specific elements or a subset, who'd've thought.\\\\
\begin{tabular}{c c}
\cleanstyle{Function/Operator}&\cleanstyle{Meaning}\\
\hline
\cleanstyle{!!}&\cleanstyle{returns the \cleanstyle{n}'th element from \cleanstyle{xs} (starts at 0)}\\
\cleanstyle{take n xs}&\cleanstyle{returns the first \cleanstyle{n} amount of elements from \cleanstyle{xs}}\\
\cleanstyle{drop n xs}&\cleanstyle{returns \cleanstyle{xs} without the last \cleanstyle{n} amount of elements}\\
\cleanstyle{\% xs (x,y)}&\cleanstyle{returns a "slice" of \cleanstyle{xs}, from index \cleanstyle{x} to \cleanstyle{y}}
\end{tabular}\linebreak\linebreak\linebreak\textbf{{\large List Comprehensions}}\\\\
I'm afraid list comprehensions won't help you comprehend lists. They're just another way to format lists: they're a way to quickly apply simple recursive functions to all elements in a list:
\\\\
\cleancode{
squareOdds :: [Int] -> [Int]\\
squareOdds xs = [\commblue{(function on) element(s)}x*x \commred{where there elements are from}\textbackslash\textbackslash\space x <- xs \commgreen{only executed if this is True}| isOdd x]\\}
This function will produce a list of all elements from \cleanstyle{xs} squared (\cleanstyle{x*x}), but only if \cleanstyle{isOdd x}. List comprehensions consist of 2 to 3 parts:
\begin{enumerate}
\item Indication of what you want to do with the elements of the list(s).\\
\tab \cleanstyle{x*x}
\item Indication of where the arguments in part 1 are from (called "generators").\\
\tab \cleanstyle{\textbackslash\textbackslash\space x <- xs}
\item(optional) Makes sure to only include the current element(s) if what comes after the"\cleanstyle{|}" is \cleanstyle{True}.\\\tab[0.5cm]
\cleanstyle{| isOdd x}
\end{enumerate}
When applying list comprehensions to multiple lists, there's 2 different ways to combine the elements: nested and parallel (i.e. pairwise).\\
\cleancode{
[(x,y) \textbackslash\textbackslash\space x <- [1,2,3], y <- [a,b,c]]\\}
This comprehension makes a list of tuples: \cleanstyle{[(Int,Char)]}. And utilizes a "\cleanstyle{,}". Comma's are used for nested generators, meaning that it'll loop through all possible combinations and produce the list\\\cleanstyle{[(1,a),(1,b),(1,c),(2,a),(2,b),(2,c),(3,a),(3,b),(3,c)]}.\\
\cleancode{
[(x,y) \textbackslash\textbackslash\space x <- [1,2,3] \& y <- [a,b,c]]\\}
This comprehension makes a list of the same type, but utilizes a \cleanstyle{\&}. This means that it only executes part one for all elements of the same index, i.e. pairwise combinations. This also means that if one list is longer than the other, the length of the list it produces is the same as that of the smallest list (which also means that the usage of infinite lists is perfectly fine). This comprehension produces the list \cleanstyle{[(1,a),(2,b),(3,c)]}
\subsection{Overloading} \label{Overloading}%------------------------------
Overloading is the act of defining operators for a new type, whether it's a tuple, record type or algebraic type. But because it's generally done in 1 line (which I'm not gonna do) the structure can be confusing.\\
\cleancode{
instance \commpurp{instance you're defining ("+" for doubles)}+ (a,b) \commgreen{given that "+" works for the elements}| + a \& + b\\
\tab[1.7cm]where\\
\tab[2.2cm]\commred{passing of operator and necessary arguments, done with a pattern}+ (x,y) (v,w)= \commblue{output as a double}(x+v, y+w)\\}The above code defines the instance for adding 2 doubles (see \underline{\nameref{Tuple}}). This is done by adding both elements of the doubles with each other, according to this instance. You might recognize the \cleanstyle{where} command from \underline{\nameref{Local Definitions}}. That's because a part of an instance definition is just a local definition, where you pass the operator and the necessary number of types (in this case 2 doubles) for using the operator.\\\\
Overloading syntax in depth:
\begin{enumerate}
\item Instance keyword, then operator and type for which you want to define the operator.\\
\tab \cleanstyle{instance + (a,b)}
\item Requirements for being able to execute this operator for this type.\\
\tab \cleanstyle{| + a \& + b}
\item Keyword for local definition.\\
\tab \cleanstyle{where}
\item Passing of operator and necessary types for executing this operator.\\
\tab \cleanstyle{+ (x,y) (v,w)}
\item Output of the function.\\
\tab \cleanstyle{= (x+v, y+w)}\\
\end{enumerate}\textbf{{\large Overloading a record type}}\\\\
When defining operators for a new record type that contains general types (like "\cleanstyle{a}", "\cleanstyle{b}", etc.), there's some extra stuff that you have to do:\\
\cleancode{
:: BadHombres a b = \{Mexico :: a, China :: b\}\\\\
instance + (BadHombres a b) | + a \& + b\\
\tab[1.7cm]where\\
\tab[2.2cm]+ h1 h2 = \{Mexico = h1.Mexico + h2.Mexico,\\
\tab[4.2cm]China = h1.China + h2.China\}\\}You
might've
noticed
that the definition of \cleanstyle{BadHombres} has a different syntax than the example in \underline{\nameref{Record Type}}. This is because the the requirements for executing the function (\cleanstyle{| + a \& + b}) need to be able to access the types in the record type.
\\\\
If you have an already defined type (whether it's a basic type, algebraic type or data structure), you don't need to pass the type. If you always use the same types for \cleanstyle{BadHombres}, for example 2 Strings, you can just write:\\
\cleancode{:: BadHombres = \{Mexico :: String, China :: String\}\\\\
instance + BadHombres | + String\\
\tab[1.7cm](...)\\}Also
note
that
if you have a general type in your record type, like in \cleanstyle{BadHombres a b :: \{...\}}, you also need to specify the types whenever you make a new \cleanstyle{BadHombres}. So like:\\
\cleancode{
CrookedHillary :: BadHombres String String\\
CrookedHillary = \{Mexico = "Rapists", China = "TradeWar"\}\\}Keep
in
mind
that you don't \textit{need} to define the type of \cleanstyle{CrookedHillary}, since \cleanstyle{Mexico} and \cleanstyle{China} together always form the type \cleanstyle{BadHombres}. So just the 2nd line is enough.
%---------------------------------------FUNCTIONS------------------------------------------
\newpage
\section{Functions} \label{Functions}%------------------------------
In a way, a function is a type as well. Just one that requires one or more arguments (which also means you can pass a function as an argument, cause it's technically a type, but we'll get to that in \underline{\nameref{Higher Order Functions}}).\\\\
Also note that for a function to work, its types don't always need to be defined, but defining types narrows the scope of a function. For example, when you have a function without type definitions that multiplies two arguments, you'd better hope no one is gonna try to pass characters or strings to the function. Therefore it's generally safer (and usually required) to define the types of a function.\\\\
Functions in clean have the following basic format:\\
\cleancode{
Contains :: \commred{input and output types}Char String -> Bool | \commblue{given that functions hd and tl work for String}hd String \& tl String \\
Contains \commgreen{'if empty string'. you can have separate functions for different inputs}c "" = False\\
Contains c s\\\tab[1.9cm] \commpurp{if-statement. Expects boolean}| c == hd s = True\\
\tab[1.9cm] | otherwise \commblue{single = assigns value to function}= Contains c tl(s)\\\\}Clean functions can be divided into 5 parts, with part 1, 2 and 4 being optional, depending on the situation:\\
\begin{enumerate}
\item Name and type definition.
\cleancode{Contains :: Char String -> Bool}
\item Requirements for being able to execute the function: "Given that you know how to...". Use \cleanstyle{\&} if multiple requirements.
\cleancode{| hd(String) tl(String)}
\item Cases for certain inputs. (called "patterns")
\cleancode{Contains c ""\\Contains c s}
\item Logical Condition(s). (preceded by "guards")
\cleancode{| c == hd s\\| otherwise}
\item Assigning a value to the function.
\cleancode{= True\\= Contains tl(s)\\}
\end{enumerate}Clean's "single line programming" approach makes it so that you often need multiple functions for a single exercise. If you get stuck and don't know how to write the function, see \underline{\nameref{Writing a Function}}.
\subsection{Recursion} \label{Recursion}%------------------------------
Recursion is the act of making a function call itself with different arguments/inputs. In clean, recursion is used a lot, mainly because it does not have loops.
\\\\
When writing a recursive function, ALWAYS include the termination case. For example:
\cleanstyle{Contains c "" = False},
then write the code for when the termination case is false. Also make sure that this code will eventually reach the termination case.
\subsubsection{For-loop in Clean} \label{For-loop in Clean}%-------------------------
(The following is more like an example of a Clean function, rather than actual study material)\\\\
Clean for-loops use \underline{\nameref{Local Definitions}} to iterate a command a certain number of times. The hard part here is to figure out what should be done in the case of \cleanstyle{i > j} because it still needs to be executed in one line of code. This is the basic structure though.\\
\cleancode{
ForLoop :: \commred{input \& output may vary}Int (...) -> a\\
ForLoop i (...) = SubLoop i 0 (...)\\
\tab[3.50cm]where\\
\tab[3.90cm]\commpurp{local definition}SubLoop i j (...)\\
\tab[4.60cm]| i > j = \commgreen{also varies}...SubLoop i (j+1) (...)\\
\tab[4.60cm]| otherwise = (...)
}
\subsection{Local Definitions} \label{Local Definitions}%------------------------------
Clean's functional nature requires you to use a lot of separate functions. Luckily, you can just define them within the function you need them in, though the structure can be confusing:\\
\cleancode{
Triangle :: Int -> String\\
Triangle n = SubTriangle \commpurp{actual values passed to SubTriangle}n 0\\
\tab[1cm]\commgreen{keyword for local def.}where\\
\tab[1cm]\commred{definition of SubTriangle with parameters}SubTriangle n m\\
\tab[1cm]| n >= 0 = space (n-1) +++ line (1+2*(m-n)) +++ "\char`\\n" +++ SubTriangle (n-1) m\\
}
Note that when defining a local definition, you don't need to specify the types of the parameters.\\\\
Local definitions can access any parameter in the function they're in, but not the other way around. Which is similar to the way that brackets work in Java.
\subsection{$\lambda$ - Abstractions} \label{Lambda Abstractions}
Clean gets scared when it sees multiple lines, so on top of local definitions, it also supports $\lambda$-abstractions.
Like local definitions, they're functions used locally, only without a name and signified with a \cleanstyle{\textbackslash}.\\
\cleancode{
doubleList :: [Int] -> [Int]\\
doubleList xs = map subdouble xs\\
\tab[1cm]where\\
\tab[1cm]subdouble x = x * 2\\
\linebreak
doubleList :: [Int] -> [Int]\\
doubleList xs = map (\textbackslash x = x * 2) xs\\
}Both functions double every element in an Int list (kudos to Matthijs), but the latter uses $\lambda$-abstraction. Within the parentheses and after a \cleanstyle{\textbackslash}, it just behaves as a regular function, with the arguments on the left hand side, and the output on the right hand side. Also, you cannot use guards in a $\lambda$-abstraction, nor can it call itself. So you'll have to use \underline{\nameref{If-Operator}} and \underline{\nameref{Accumulators}}.
\subsubsection{Accumulators} \label{Accumulators}
UPDATE: It's part of the exam after all.
\\\\
Accumulators are mainly used in $\lambda$-abstractions as limited way of making them recursive. This is because a $\lambda$-abstraction does not have a name and therefore cannot call itself. It can instead use an accumulator, which stores the previous outcome of the function. Please note that there's only a single slide that covers accumulators and personally I can't make chocolate of it.\\
\cleancode{
\textcolor{black}{1.) }sumList xs = foldl (+) 0 xs\\\\
\textcolor{black}{2.) }sumList xs = foldl (\textbackslash x acc = acc + x) 0 xs\\\\
\textcolor{black}{3.) }sumList xs = subSum 0 xs\\
\tab[0.95cm]where\\
\tab[1.5cm]subSum acc [] = acc\\
\tab[1.5cm]subSum acc [x:xs] = subSum (acc + x) xs\\\\
Start = sumList [1,2,3]\\}(For
more
info
on \texttt{foldl} see \underline{\nameref{fold}})
\\\\
The above functions all add every element of a list to each other, but the last 2 use accumulators. However, it looks like function \texttt{3} might have just used any other name instead of \cleanstyle{acc} and still work the exact same, so I'm not sure to what extent it's actually an accumulator.
\\\\
To me, using an accumulator in a $\lambda$-abstraction makes the most sense. Since you can only pass it known arguments, the code-word \cleanstyle{acc} must (in my logic) automatically indicate an accumulator. As opposed to function \texttt{3} where it can be any other word or letter. Plus, as I've said before, it can help to make up for that fact that a $\lambda$-abstraction cannot call itself.
\\\\
So let's take function \texttt{2} as our example: the initial value of an accumulator is always \cleanstyle{zero}, which means it can also be used for any other data type that supports that value, not just numbers. Anyways, \cleanstyle{foldl} is executed as long as it gets an argument (in this case \cleanstyle{x}), so we move to the first element of the list, \cleanstyle{1}, and execute the function: \cleanstyle{x + acc = 1 + 0 = 1}. This value is then stored in the accumulator, since that was the last output of the $\lambda$-abstraction. Next, \cleanstyle{foldl} moves on to the 2nd element: \cleanstyle{x + acc = 2 + 1 = 3}. This is then stored in the accumulator again, and the next and last element of the list is passed: \cleanstyle{x + acc = 3 + 3 = 6}. At this point \cleanstyle{foldl} runs out of arguments and outputs the last computed value of the $\lambda$-abstraction (or the accumulator, since it stores the last output anyways).
\\\\
The weird thing between function \texttt{1} and \texttt{2} is that the accumulator in \texttt{2} doesn't seem to even use the \cleanstyle{0} that's passed to \cleanstyle{foldl}, whereas in function \texttt{1} it \textit{is} used. This is more noticeable when using a similar structure to calculate the length of a list. Also, this has probably more to do with \cleanstyle{foldl} than with the accumulator, but keep it in mind.
\subsection{The If-Operator} \label{If-Operator}
You can use Clean's if-operator as an alternative for guards. Which can be helpful in $\lambda$-abstractions because you can't use guards there.\\
\cleancode{
if\commpurp{boolean}(cold tomorrow) \commgreen{if True}wearCoat \commred{if False}wearShorts\\}The \cleanstyle{if()} function takes one boolean, then executes the first argument if \cleanstyle{True}, and the second argument if \cleanstyle{False}. This seems limited, but remember you can put something in parentheses if you want it to be regarded as one argument. This includes another if-statement, resulting in an "if, else if" situation.
%takeWhile = \f -> foldr (\x acc -> if (f x) [x:acc][])[]
\subsection{Higher Order Functions} \label{Higher Order Functions}%------------------------------
Because functions are technically types too, they can also be used as arguments. These kinds of functions are called "higher order functions". Though dissecting higher order functions can be confusing:\\
\cleancode{
f1 a b c = a c (b c)\\
}This is an example of a higher order function without type definitions. At first glance, it seems like the function outputs two arguments and one tuple that's missing a comma. Which shouldn't be possible. And it isn't: some of these arguments are functions.
\\\\
To figure out the structure of these functions, you have to look at the right hand side of the \cleanstyle{=} sign, from which you can concludee a few things:
\begin{enumerate}
\item \cleanstyle{a} is a function, since more arguments follow.
\item \cleanstyle{c} is not a function, since (within the parentheses) no arguments follow. Also, \cleanstyle{c} cannot be a function with \cleanstyle{b} and \cleanstyle{c} as arguments, since that means \cleanstyle{c} is a function with 2 arguments, and no arguments at the same time.
\item \cleanstyle{b} is a function, since (within the parentheses) one argument follows.
\end{enumerate}
This means that \cleanstyle{a} is the main function, with type \cleanstyle{t t -\textgreater\space t}, since it takes two arguments and returns one. \cleanstyle{b} has type \cleanstyle{t -\textgreater\space t} and \cleanstyle{c} has type \cleanstyle{t}. Meaning that the types of function \cleanstyle{f1} are:\\
\cleancode{
f1 :: (a a -> a) (a -> a) a \commblue{The type of the output is whatever is after the last "-\textgreater "}-> a\\
f1 a b c = a c (b c)\\
}As
you
can
see, when defining a type as a function, you need to use parentheses "()". This also holds when you define one function to be another function entirely:\\
\cleancode{
f2 :: a -> a\\
f2 x = x\\
\\
f3 :: (a -> a)\\
f3 = f2\\\\
}
\textbf{\large Tips for Structure of Higher Order Functions}\\\\
Look at the right hand and left hand side of the function and use logic to determine which arguments are functions and which are arguments. Then determine how many arguments each function takes and, if needs be, the specific type of their input and output. Some tips:
\begin{itemize}
\item Look at the arguments in the pattern, and define them one by one. If it is a function, use parentheses.
\item Look at what arguments need to be put together in order to make a single type.
\item When needing to put arguments together, the first one is always a function and anything following (including the stuff in parentheses) are arguments for that function. Ex: \cleanstyle{(a b,c d)} is a tuple, which has as type \cleanstyle{(t,t)}. Therefore \cleanstyle{a} is a function with \cleanstyle{b} as an argument, etc.
\item Something in parentheses is always a function of its own. Ex: \cleanstyle{a c (b c)} here \cleanstyle{a} is a function, \cleanstyle{c} and \cleanstyle{(b c)} are arguments. And within the parentheses, \cleanstyle{b} is a function with \cleanstyle{c} as an argument.
\item If you define one of your types as a function, and it also happens to have another function inside of it (like \cleanstyle{a c (b c)}), you don't need to specify the types of that function within the function you're defining, just defining the number of arguments is enough: \cleanstyle{a} as \cleanstyle{(t t -\textgreater\space t)}.
\item If you wanna be really cheeky, defining the wrong types can cause Clean to print the cases for which the function doesn't work in the error window. Sometimes simply copying the types of one of these cases fixes your problem.
\end{itemize}
\subsubsection{Currying}
If only it was as nice as actual curry.\\\\Currying can only be done with \underline{\nameref{Higher Order Functions}}. It's when you leave out one or more arguments from the function in your higher order function. You can then place that argument, after calling the higher order function itself. For example, the following function takes a function and a number:\\
\cleancode{
negate :: (a -\textgreater\space a) a -\textgreater\space a | {\raise.17ex\hbox{$\scriptstyle\sim$}} a\\
negate f x = {\raise.17ex\hbox{$\scriptstyle\sim$}}f x\\\\
square x = x * x\\\\
Start = negate square 2\\
}This will return \cleanstyle{-4}, the negation of the argument squared. However, you can also omit \cleanstyle{x} in \cleanstyle{negate}, by which you curry the function:\\
\cleancode{
curriedNegate :: (a -\textgreater\space a) -\textgreater\space (a -\textgreater\space a) | {\raise.17ex\hbox{$\scriptstyle\sim$}} a\\
curriedNegate f = {\raise.17ex\hbox{$\scriptstyle\sim$}}f\\\\
Start = negate square 2\\}This will also return \cleanstyle{-4}, but clean chops the code up differently. First it calls the function \cleanstyle{negate}, which only takes one argument as you can see in the type definition. So Clean will initially only look for one argument and read the code as \cleanstyle{(negate square) 2}.
\\\\
The outcome however, is also a function which takes one argument. So clean sees that the code in parentheses has a function as output, and then looks at the next piece of code for the argument for that function, which in this case is \cleanstyle{2}.
\\\\Keep in mind that you can only curry the last arguments of a function. If you wanna curry an argument but put it somewhere in the middle of your function, you have to use some forbidden Clean magic that you couldn't find even if you tried.
%-------------------------------------TIPS & TRICKS---------------------------------------
\subsection{\cleanstyle{\textcolor{black}{foldr}} and \cleanstyle{\textcolor{black}{foldl}}} \label{fold}
Never thought these shitty functions would be important enough to be an exam topic.
\\\\
In order to understand \cleanstyle{foldr} and \cleanstyle{foldl}, you need to under stand how Clean reads lists. When you make the list \cleanstyle{[1,2,3]} Clean interprets it as \cleanstyle{[1:[2:[3:[]]]]}.
\\\\
Both \cleanstyle{fold} functions require an operator / function, a starting value and a list, in that order. They then apply that function to the list, much like \cleanstyle{map}. But unlike \cleanstyle{map}, it combines elements of a list in a certain way, rather than changing its elements.\cleanstyle{foldr} as the following structure (might help you understand it):\\
\cleancode{
foldr op r [a:x] = op a (foldr op r x)\\
foldr op r [] = r\\
}
There's 2 ways to use the \cleanstyle{fold} functions, with an operator and with a function (which is often a $\lambda$-abstraction).
\\\\
Let's use \cleanstyle{foldr} with \cleanstyle{(+)} and \cleanstyle{0} on our previous list. The function changes all the \cleanstyle{:} into the operator you passed it, and puts a \cleanstyle{0} in the empty list to the right (if using \cleanstyle{foldl} it'll place it on the left). Meaning that \cleanstyle{[1:[2:[3:[]]]]} turns into \cleanstyle{(1+(2+(3+(0))))}, which is \cleanstyle{6}.
\\\\
You might be wondering why you even need the \cleanstyle{0}. That's because different operators have different base values. When you add \cleanstyle{0} to something, it stays the same. If we wanted to get the product of a list instead of the sum, we would write \cleanstyle{foldr (*) 1 xs}, because multiplying something by \cleanstyle{1} doesn't change that something.
\\\\
For the other way of using the \cleanstyle{fold} functions (with a function instead of an operator) I'm gonna use a $\lambda$-abstraction with an accumulator and if-statement, because that's the only way I know how to do it.
\\\\
The following $\lambda$-abstraction basically returns \cleanstyle{x} if it's higher than the accumulator, otherwise it returns the accumulator, which stores the previous outcome of the $\lambda$-abstraction (see \underline{\nameref{Lambda Abstractions}}, \underline{\nameref{Accumulators}}, and \underline{\nameref{If-Operator}} if you need to know more).\\
\cleancode{
foldl (\textbackslash x acc = if(x \textgreater\space acc) x acc) 0 xs\\
}Applying
this
to
\cleanstyle{foldr} means that it loops through every element in the list and returns the highest number.
\\\\
According to my Clean logic, which isn't always right cause it's Clean after all, the only major difference between the operator version and the function version of \cleanstyle{foldr} and \cleanstyle{foldl} is that when passing it a function it actually doesn't seem to utilize the number you pass it. But I might be wrong about that.
\newpage
\section{Tips, Tricks \& Miscellaneous} \label{Tips & Tricks}%------------------------------
\subsection{Program Reasoning}
\subsubsection{Induction}
Induction can seem really confusing, but it's actually really simple. Just like in formal reasoning, there's a template for proving induction. The only parts that you actually have to think about are the base case and the induction step.
\\\\
In this example we'll use the operator \cleanstyle{++} and the function \cleanstyle{map}, which applies a function to every element in a list. Let's say you're given the following definition of the \cleanstyle{++} operator on lists, and the \cleanstyle{map} function:\\
\cleancode{
(++) :: [a] [a] -\textgreater\space [a]\\
(++) [] ys = ys\tab[4.1cm]\textcolor{black}{(1)}\\
(++) [x:xs] ys = [x : xs ++ ys]\tab[1cm]\textcolor{black}{(2)}
\\\\
map :: (a -\textgreater\space b) [a] -\textgreater\space [b]\\
map f [] = []\tab[4.5cm]\textcolor{black}{(3)}\\
map f [x:xs] = [f x : map f xs]\tab[1cm]\textcolor{black}{(4)}\\}And
you
have
to prove that \cleanstyle{map f (as ++ bs) = (map f as) ++ (map f bs)}. So the mapping of the combined list of \cleanstyle{as} and \cleanstyle{bs} is the same as the mapping of \cleanstyle{as} combined with the mapping of \cleanstyle{bs}.
\\\\
The numbered lines in the definitions of \cleanstyle{++} and \cleanstyle{map} are free to use in your proof.
\\
\cleancode{\textcolor{black}{
Prove: for all as :: [a] : map f (as ++ bs) = (map f as) ++ (map f bs)\\
Proof: by induction on as\\}}First
up
is
the proof of the base case. For this, just make the argument you're applying induction to \cleanstyle{zero}. You always apply induction to only 1 argument, which in this case is \cleanstyle{as}, so let's take \cleanstyle{as} and make it \cleanstyle{[]}. Now you have to transform the equation so that both sides are equal:\\
\cleancode{\textcolor{black}{
Base case:\\
assume as = []\\\\
Prove: map f (as ++ bs) = (map f as) ++ (map f bs)\\\\
Proof:\\
(ass.)\tab[1.17cm] map f (as ++ bs) = (map f as) ++ (map f bs)\\
(1)\tab[1cm]\textless =\textgreater\space map f (\underline{[] ++ bs}) = (map f []) ++ (map f bs)\\
(3)\tab[1cm]\textless =\textgreater\space map f bs = (\underline{map f []}) ++ (map f bs)\\
(1)\tab[1cm]\textless =\textgreater\space map f bs = \underline{[] ++ (map f bs)}\\
\tab[1.55cm]\textless =\textgreater\space map f bs = map f bs\\}}Note
that
the
"\cleanstyle{\textcolor{black}{\textless =\textgreater }}" is required for the proof, as are the indications of what rules you used (like "\cleanstyle{\textcolor{black}{(3)}}").\\\\
With the base case proven, now we move on to the induction step. Proving the induction step is similar to the base case in the way that you aim to make both sides of the equation equal. But before that, you have to substitute a part of your induction step by your induction hypothesis (IH). The induction step for a list is always the IH with an extra head:\\
\cleancode{\textcolor{black}{
Induction Case:\\
Assume property holds for certain as:\\
map f (as ++ bs) = (map f as) ++ (map f bs)\tab[1cm](IH)
\\\\
Prove:map f ([a:as] ++ bs) = (map f [a:as]) ++ (map f bs)\\\tab[1cm]for all a\\\\
Proof:
\\
\cleanstyle{\textcolor{black}{(4)\tab[1.23cm] map f ([a:as] ++ bs) = (\underline{map f [a:as]})++(map f bs)}}
\\
\cleanstyle{\textcolor{black}{\tab[1.05cm]\textless =\textgreater\space map f ([a:as] ++ bs) = \underline{[f a:map f as]} ++ (map f bs)}}
\\
\cleanstyle{\textcolor{black}{(IH)\tab[0.3cm]\textless =\textgreater\space map f ([a:as] ++ bs) = [f a] ++ \underline{(map f as) ++ (map f bs)}}}
\\
\cleanstyle{\textcolor{black}{(2)\tab[0.5cm]\textless =\textgreater\space \underline{map f ([a:as] ++ bs)} = [f a] ++ map f (as ++ bs)}}
\\
\cleanstyle{\textcolor{black}{\tab[1.05cm]\textless =\textgreater\space map f [a:as ++ bs] = \underline{[f a] ++ map f (as ++ bs)}}}
\\
\cleanstyle{\textcolor{black}{(4)\tab[0.5cm]\textless =\textgreater\space \underline{map f [a:as ++ bs]} = [f a : map f (as ++ bs)]}}
\\
\cleanstyle{\textcolor{black}{\tab[1.05cm]\textless =\textgreater\space [f a : map f (as ++ bs)] = [f a : map f (as ++ bs)]}}
\\\\
Base + Induction proof complete.\\
}}And
that's
the
format of induction proof that you have to use.
\subsubsection{Applicative vs. Normal Order}
A program can be evaluated in 2 ways: via applicative order (arguments first), and via normal order (left-most function first). Both aim to reduce the program / function to its \textit{normal form}, which is the form when nothing needs to be computed anymore, i.e. the output of the function.\\\\
As for an example, take the following code:\\
\cleancode{
square n = n * n\\
inc n = n + 1\\
square\_inc n = square (inc n)\\\\
Start = square\_inc 7\\
}This
is
reduction
by \textbf{applicative order}, which is what Clean uses:\\
\cleancode{
Start\\
= square\_inc 7\\
= square (inc 7)\\
= square (7 + 1)\\
= square 8\\
= 8 * 8\\
= 64\\}And
this
by
\textbf{normal order}, which is what Java uses.\\
\cleancode{
Start\\
= square\_inc 7\\
= square (inc 7)\\
= (inc 7) * (inc 7)\\
= (7 + 1) * (inc 7)\\
= 8 * (inc 7)\\
= 8 * (7 + 1)\\
= 8 * 8\\
= 64}
\subsection{Programming \& Exam Tips} \label{Programming Tips}%------------------------------
\subsubsection{Writing a Function} \label{Writing a Function}
There's no one way to write a function, but there are some general steps you can take with which you can cheese more than you'd think:\\
\begin{enumerate}
\item First determine the output of the function, and the ways you can (combine stuff to) get that output. e.g. a function that loops through a list and returns a \cleanstyle{Bool}, can just call itself with the tail of the list, since that function is also a \cleanstyle{Bool}, and if you need to output a list or a list of lists, keep the ways you can combine lists in mind, like \cleanstyle{:} or \cleanstyle{++}.
\item Divide the stuff that you need to do into chunks, while thinking of Clean's limitations and possibilities (don't thinks of the exact syntax yet). Also check the StdEnv, maybe there's a function in there that already solves a part of your problem.
\item If you need arguments that aren't passed by the original function and that are always the same, or just something that loops a certain number of times, use a local definition. Local definitions can be stacked, so don't skimp on 'em.
\item Write the patterns for the possible cases, starting with the most specific cases (like the base case) and work your way to the most general one.
\item If there's multiple cases that have the same pattern (e.g. when 2 arguments are the same, do this. Otherwise, do that) use guards. You can also stack guards, but make sure the indent is correct.
\item If you're still stuck after this, it's probably because of a trick with a specific type that you need to use (like the difference between the \cleanstyle{,} and \cleanstyle{\&} operators in list comprehensions), or some special Clean magic that only the TA's and Peter know.\\
\end{enumerate}
In short, the golden combination for writing a function is usually determining the output type(s), patterns, local definitions and guards. As for some general tips when writing a function:\\
\begin{itemize}
\item When writing the actual code, remember that a single \cleanstyle{=} sign is always used to assign a value to either the output, or a type in the output (like in a record type).
\item Don't forget the StdEnv!
\item I can't stress this enough but make sure you know the difference between assigning a type (\cleanstyle{::}) and assigning a value (\cleanstyle{=}). This is especially important when working with record types.
\item If you get a "cannot unify types" error but you haven't got a clue why, try deleting the functions type definition, cause sometimes you just didn't write it properly.
\end{itemize}
\subsubsection{Determining a Function's Output}
When trying to figure out the output of a function (something that's going to be asked on the exam), you have to look at the code like Clean does, meaning that you first have to calculate the stuff "in parentheses". For example, in the first exercise of the exam of June 2016 the output of the function \cleanstyle{same\_begin [3,2,2,1,2] [3,2,1,2]} is asked, with as function body:\\
\cleancode{same\_begin as bs
= map fst
(takeWhile (\textbackslash (a,b) -\textgreater a == b)\\\tab[3.4cm]
[ (a,b) \textbackslash\textbackslash\space a \textless - as \& b \textless - bs ])\\
}Start
left,
and determine how many and what kind of arguments each part needs. \cleanstyle{map} is a function that needs a function and a list. But the list is not that clear, cause it's this long thing in parentheses. So you first change that part into a list.\\\\\cleanstyle{takeWhile} is a function of type \cleanstyle{(a -\textgreater\space Bool) [a] -\textgreater\space [a]}. And it outputs all elements of a list for which the boolean holds. In this case the boolean is the $\lambda$-abstraction \cleanstyle{(\textbackslash (a,b) = a == b)}, which returns \cleanstyle{True} is both elements of the double are equal. This boolean is then applied to the list \cleanstyle{[(a,b) \textbackslash\textbackslash\space a \textless - as \& b \textless - bs]}. Note the \cleanstyle{\&}, this means that it combines the elements of the list pair wise (so only the ones with the same index).
\\\\
Now that you know what each part produces, combine them into the solution of the function:\\
\begin{enumerate}
\item \cleanstyle{as = [3,2,2,1,2]} and \cleanstyle{bs = [3,2,1,2]}. The list comprehension outputs the pairwise combinations. so:
\\\tab \cleanstyle{[(3,3), (2,2), (2,1), (1,2)]}
\item \cleanstyle{takeWhile} only takes the doubles whose elements have the same value:
\\\tab \cleanstyle{[(3,3), (2,2)]}
\item \cleanstyle{fst} takes the first element of a double, and \cleanstyle{map} applies it to the elements of the list we just made. Making the eventual output of the function:
\\\tab \cleanstyle{[3,2]}\\
\end{enumerate}
One more cheeky trick: if you don't understand the definition of a function in the exam, the name can actually reveal quite a bit.
\subsection{Error Message Comprehension} \label{Error Message Comprehension}%------------
Even reading ancient Greek would be easier than deciphering Clean's error window. Here's something to help you out:\\
\begin{itemize}
\item \textbf{Linker error: could not create 'C:\textbackslash Users...Exercise.exe'}\\\tab\textit{Don't worry, you just didn't close your previous .exe window.\\\tab Close it and try again.}
\item\textbf{Error [Exercise.icl,1,Start]: has not been declared}\\\tab\textit{Your code is missing the 'Start =' command.}
\item\textbf{Type error [Exercise.icl,31,Start]:"..." cannot unify types:\linebreak[4] [Int]\linebreak[4] Int}\\\tab\textit{You messed something up with the brackets.} (), [] \textit{or} \{\}
\item\textbf{Parse error [Exercise.icl,31;4,Type name]: upper case ident expected instead of \textless type\textgreater}\\\tab\textit{You need to capitalize the first letter of your new type.}
\item\textbf{Parse error [FQL.icl,58;116,nested guards]: sorry, but for the time being there is a default alternative for nested guards expected
}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
% \item\textbf{}\\\tab\textit{}
\end{itemize}
\subsection{Troubleshooting} \label{Troubleshooting}%------------------------------
\subsection{Secret StdEnv Commands} \label{Secret StdEnv Commands}%----------------------
Because there's not really a way to Ctrl + F at specific pages, I decided to make the list of stdEnv commands a separate document: \url{https://www.overleaf.com/read/sjdrqxdrfkcd} \textit{Won't be working on this until after the exam. Use Functional Programming in Clean for now.}
\subsection{Helpful Links} \label{Helpful Links}%------------------------------
Functional Programming in Clean (2002)\\
\url{http://www.mbsd.cs.ru.nl/publications/papers/cleanbook/CleanBookI.pdf}\\\\
A Concise Guide to Clean StdEnv (2011)\\
\url{http://www.mbsd.cs.ru.nl/publications/papers/2010/CleanStdEnvAPI.pdf}
\end{document}