(somefunc a) >> (otherfunc b)
\stophaskell
-\todo{Properly introduce >>=}
-There is also the \hs{>>=} operator, which allows for passing variables from
-one expression to the next. If we could use this notation to compose a
-stateful computation from a number of other stateful functions, this could
-move all the boilerplate code into the \hs{>>} operator. Perhaps the compiler
-should be taught to always inline the \hs{>>} operator, but after that there
-should be no further changes required to the compiler.
+The main reason to have the monadic notation, is to be able to wrap
+results of functions in a datatype (the \emph{monad}) that can contain
+extra information, and hide extra behaviour in the binding operators.
+
+The \hs{>>=} operator allows extracting the actual result of a function
+and passing it to another function. Let's try to illustrate this from an
+example. The following snippet:
+
+\starthaskell
+do
+ x <- somefunc a
+ otherfunc x
+\stophaskell
+
+will be desugared into:
+
+\starthaskell
+(somefunc a) >>= (\\x -> otherfunc x)
+\stophaskell
+
+The \hs{\\x -> ...} notation creates a lambda abstraction in Haskell,
+that binds the \hs{x} variable. Here, the \hs{>>=} operator is supposed
+to extract whatever result somefunc has and pass it to the lambda
+expression created. This will probably not make the monadic notation
+completely clear to a reader without prior experience with Haskell, but
+it should serve to understand the following discussion.
+
+The monadic notation could perhaps be used to compose a number of
+stateful functions into another stateful computation. Perhaps this could
+move all the boilerplate code into the \hs{>>} and \hs{>>=} operators.
+Because the boilerplate is still there (it's not magically disappeared,
+just moved into these functions), the compiler should still be able to compile
+these descriptions without any special magic (though perhaps it should
+always inline the binding operators to reveal the flow of values).
This is highlights an important aspect of using a functional language for our
descriptions: We can use the language itself to provide abstractions of common
choices, we've tried to stick with the most obvious choice wherever
possible. In a lot of cases, when you look at a hardware description it is
comletely clear what hardware is described. We want our translator to
- generate exactly that hardware whenever possible, to minimize the amount of
- surprise for people working with it.
+ generate exactly that hardware whenever possible, to make working with Cλash
+ as intuitive as possible.
In this chapter we try to describe how we interpret a Haskell program from a
hardware perspective. We provide a description of each Haskell language
\startbuffer[CaseInv]
inv :: Bool -> Bool
- inv True = False
- inv False = True
+ inv x = case x of
+ True -> False
+ False -> True
\stopbuffer
\startuseMPgraphic{CaseInv}
\placeexample[here][ex:PatternInv]{Simple inverter using pattern matching.
Describes the same architecture as \in{example}[ex:CaseInv].}
- {\typebufferhs{CaseInv}}
+ {\typebufferhs{PatternInv}}
The architecture described by \in{example}[ex:PatternInv] is of course the
same one as the one in \in{example}[ex:CaseInv]. The general interpretation
To define an index for the 8 element vector above, we would do:
\starthaskell
- type Register = RangedWord D7
+ type RegisterIndex = RangedWord D7
\stophaskell
Here, a type synonym \hs{RegisterIndex} is defined that is equal to
\subsection{User-defined types}
There are three ways to define new types in Haskell: Algebraic
datatypes with the \hs{data} keyword, type synonyms with the \hs{type}
- keyword and type renamings with the \hs{newtype} keyword. This
- explicitly excludes more advanced type creation from \GHC extensions
- such as type families, existential typing, \small{GADT}s, etc.
-
- The first of these actually introduces a new type, for which we provide
- the \VHDL translation below. The latter two only define new names for
+ keyword and type renamings with the \hs{newtype} keyword. \GHC
+ offers a few more advanced ways to introduce types (type families,
+ existential typing, \small{GADT}s, etc.) which are not standard
+ Haskell. These will be left outside the scope of this research.
+
+ Only an algebraic datatype declaration actually introduces a
+ completely new type, for which we provide the \VHDL translation
+ below. Type synonyms and renamings only define new names for
existing types (where synonyms are completely interchangeable and
- renamings need explicit conversion). Therefore, these don't need any
- particular \VHDL translation, a synonym or renamed type will just use
- the same representation as the equivalent type.
+ renamings need explicit conversion). Therefore, these don't need
+ any particular \VHDL translation, a synonym or renamed type will
+ just use the same representation as the original type. The
+ distinction between a renaming and a synonym does no longer matter
+ in hardware and can be disregarded in the generated \VHDL.
For algebraic types, we can make the following distinction:
structure. In fact, the builtin tuple types are just algebraic product
types (and are thus supported in exactly the same way).
- The "product" in its name refers to the collection of values belonging
+ The \quote{product} in its name refers to the collection of values belonging
to this type. The collection for a product type is the cartesian
product of the collections for the types of its fields.
- These types are translated to \VHDL, record types, with one field for
+ These types are translated to \VHDL record types, with one field for
every field in the constructor. This translation applies to all single
- constructor algebraic datatypes, including those with no fields (unit
- types) and just one field (which are technically not a product).
+ constructor algebraic datatypes, including those with just one
+ field (which are technically not a product, but generate a VHDL
+ record for implementation simplicity).
\stopdesc
\startdesc{Enumerated types}
\defref{enumerated types}
for our purposes this distinction does not really make a difference,
so we'll leave it out.
+ The \quote{sum} in its name refers again to the collection of values
+ belonging to this type. The collection for a sum type is the
+ union of the the collections for each of the constructors.
+
Sum types are currently not supported by the prototype, since there is
no obvious \VHDL alternative. They can easily be emulated, however, as
we will see from an example:
connected to one of the adder inputs).
This notation has a number of downsides, amongst which are limited
- readability and ambiguity in the interpretation. \note{Reference
+ readability and ambiguity in the interpretation. \todo{Reference
Christiaan, who has done further investigation}
\subsubsection{Explicit state arguments and results}