https://wiki.haskell.org/api.php?action=feedcontributions&user=Amy+de+B&feedformat=atomHaskellWiki - User contributions [en]2024-03-19T08:57:33ZUser contributionsMediaWiki 1.35.5https://wiki.haskell.org/index.php?title=Arrow_tutorial&diff=58584Arrow tutorial2014-07-15T18:05:42Z<p>Amy de B: The example I added may not be helpful; removed it.</p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Arrow]]<br />
<haskell><br />
<br />
> {-# LANGUAGE Arrows #-}<br />
> module ArrowFun where<br />
> import Control.Arrow<br />
> import Control.Category<br />
> import Prelude hiding (id,(.))<br />
<br />
</haskell><br />
<br />
== The Arrow ==<br />
Arrow a b c represents a process that takes as input something of<br />
type b and outputs something of type c.<br />
<br />
Arr builds an arrow out of a function. This function is<br />
arrow-specific. Its signature is<br />
<br />
<haskell><br />
<br />
arr :: (Arrow a) => (b -> c) -> a b c<br />
<br />
</haskell><br />
<br />
Arrow composition is achieved with (>>>). This takes two arrows<br />
and chains them together, one after another. It is also arrow-<br />
specific. Its signature is:<br />
<br />
<haskell><br />
<br />
(>>>) :: (Arrow a) => a b c -> a c d -> a b d<br />
<br />
</haskell><br />
<br />
First and second make a new arrow out of an existing arrow. They<br />
perform a transformation (given by their argument) on either<br />
the first or the second item of a pair. These definitions are<br />
arrow-specific. Their signatures are:<br />
<br />
<haskell><br />
<br />
first :: (Arrow a) => a b c -> a (b, d) (c, d)<br />
second :: (Arrow a) => a b c -> a (d, b) (d, c)<br />
<br />
</haskell><br />
<br />
First and second may seem pretty strange at first, but they'll make sense <br />
in a few minutes.<br />
<br />
That's it for the arrow-specific definitions.<br />
<br />
== A Simple Arrow ==<br />
Let's define a really simple arrow as an example. Our simple arrow is <br />
just a function mapping an input to an output. We don't really need <br />
arrows for something this simple, but we could use something this <br />
simple to explain arrows.<br />
<br />
<haskell><br />
<br />
> newtype SimpleFunc a b = SimpleFunc {<br />
> runF :: (a -> b)<br />
> }<br />
><br />
> instance Arrow SimpleFunc where<br />
> arr f = SimpleFunc f<br />
> first (SimpleFunc f) = SimpleFunc (mapFst f)<br />
> where mapFst g (a,b) = (g a, b)<br />
> second (SimpleFunc f) = SimpleFunc (mapSnd f)<br />
> where mapSnd g (a,b) = (a, g b)<br />
><br />
> instance Category SimpleFunc where<br />
> (SimpleFunc g) . (SimpleFunc f) = SimpleFunc (g . f)<br />
> id = arr id<br />
<br />
</haskell><br />
<br />
== Some Arrow Operations ==<br />
Now lets define some operations that are generic to all arrows.<br />
<br />
Split is an arrow that splits a single value into a pair of duplicate<br />
values:<br />
<br />
<haskell><br />
<br />
> split :: (Arrow a) => a b (b, b)<br />
> split = arr (\x -> (x,x))<br />
<br />
</haskell><br />
<br />
Unsplit is an arrow that takes a pair of values and combines them<br />
to return a single value:<br />
<br />
<haskell><br />
<br />
> unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d<br />
> unsplit = arr . uncurry <br />
> -- arr (\op (x,y) -> x `op` y)<br />
<br />
</haskell><br />
<br />
(***) combines two arrows into a new arrow by running the two arrows<br />
on a pair of values (one arrow on the first item of the pair and one arrow on the <br />
second item of the pair).<br />
<br />
<haskell><br />
<br />
f *** g = first f >>> second g<br />
<br />
</haskell><br />
<br />
(&&&) combines two arrows into a new arrow by running the two arrows on <br />
the same value:<br />
<br />
<haskell><br />
<br />
f &&& g = split >>> first f >>> second g<br />
-- = split >>> f *** g<br />
<br />
</haskell><br />
<br />
LiftA2 makes a new arrow that combines the output from two arrows using <br />
a binary operation. It works by splitting a value and operating on <br />
both halfs and then combining the result:<br />
<br />
<haskell><br />
<br />
> liftA2 :: (Arrow a) => (b -> c -> d) -> a e b -> a e c -> a e d<br />
> liftA2 op f g = split >>> first f >>> second g >>> unsplit op<br />
> -- = f &&& g >>> unsplit op<br />
<br />
</haskell><br />
<br />
<br />
== An Example ==<br />
Now let's build something using our simple arrow definition and<br />
some of the tools we just created. We start with two simple<br />
arrows, f and g. F halves its input and g triples its input and<br />
adds one:<br />
<br />
<haskell><br />
<br />
> f, g :: SimpleFunc Int Int<br />
> f = arr (`div` 2)<br />
> g = arr (\x -> x*3 + 1)<br />
<br />
</haskell><br />
<br />
We can combine these together using liftA2:<br />
<br />
<haskell><br />
<br />
> h :: SimpleFunc Int Int<br />
> h = liftA2 (+) f g<br />
><br />
> hOutput :: Int<br />
> hOutput = runF h 8<br />
<br />
</haskell><br />
<br />
What is h? How does it work? <br />
The process defined by h is (split >>> first f >>> second g >>> unsplit (+)).<br />
Lets work through an application of h to some value, 8:<br />
<br />
8 -> (8, 8) split<br />
(8, 8) -> (4, 8) first f (x `div` 2 of the first element)<br />
(4, 8) -> (4, 25) second g (3*x + 1 of the second element)<br />
(4, 25) -> 29 applies (+) to tuple elements.<br />
<br />
+------> f ---------+<br />
| v<br />
8 ---> (split) (unsplit (+)) ----> 29<br />
| ^<br />
+------> g ---------+<br />
<br />
so we see that h is a new arrow that when applied to 8, applies 8 to f <br />
and applies 8 to g and adds the results.<br />
<br />
A lot of juggling occurred to get the plumbing right since<br />
h wasn't defined as a linear combination of arrows. GHC has<br />
a do-notation that simplifies this in a similar way to how<br />
do-notation simplifies monadic computation. The h function<br />
can be defined as:<br />
<br />
<haskell><br />
<br />
> h' :: SimpleFunc Int Int<br />
> h' = proc x -> do<br />
> fx <- f -< x<br />
> gx <- g -< x<br />
> returnA -< (fx + gx)<br />
><br />
> hOutput' :: Int<br />
> hOutput' = runF h' 8<br />
<br />
</haskell><br />
<br />
== Kleisli Arrows ==<br />
Let's move on to something a little fancier now: Kleisli arrows. <br />
A Kleisli arrow (Kleisli m a b) is the arrow (a -> m b) for all<br />
monads. It's defined in Control.Arrows similarly to our SimpleFunc:<br />
<br />
<haskell><br />
<br />
newtype Kleisli m a b = Kleisli {<br />
runKleisli :: (a -> m b) <br />
}<br />
<br />
</haskell><br />
<br />
It comes complete with its own definitions for arr, first, second and<br />
(>>>). This means that all multi-value functions (a -> [b]) are already <br />
defined as Kleisli arrows (because [] is a monad)! (>>>) performs<br />
composition, keeping track of all the multiple results. Split, (&&&)<br />
and (***) are all defined as before. So for example:<br />
<br />
<haskell><br />
<br />
> plusminus, double, h2 :: Kleisli [] Int Int<br />
> plusminus = Kleisli (\x -> [x, -x])<br />
> double = arr (* 2)<br />
> h2 = liftA2 (+) plusminus double <br />
><br />
> h2Output :: [Int]<br />
> h2Output = runKleisli h2 8<br />
<br />
</haskell><br />
<br />
== A Teaser ==<br />
Finally, here is a little teaser. There is an arrow function called<br />
returnA which returns an identity arrow. There is an ArrowPlus class <br />
that includes a zeroArrow (which for the list monad is an arrow that <br />
always returns the empty list) and a <+> operator (which takes the <br />
results from two arrows and concatenates them). We can build up <br />
some pretty interesting string transformations (the multi-valued<br />
function String -> [String]) using Kleisli arrows:<br />
<br />
<haskell><br />
<br />
> main :: IO ()<br />
> main = do<br />
> let<br />
> prepend x = arr (x ++)<br />
> append x = arr (++ x)<br />
> withId t = returnA <+> t<br />
> xform = (withId $ prepend "<") >>><br />
> (withId $ append ">") >>><br />
> (withId $ ((prepend "!") >>> (append "!")))<br />
> xs = ["test", "foobar"] >>= (runKleisli xform)<br />
> mapM_ putStrLn xs<br />
<br />
</haskell><br />
<br />
An important observation here is that<br />
f >>> g<br />
<br />
is multi-valued composition (g . f), and<br />
(withId f) >>> (withId g) =<br />
(returnA <+> f) >>> (returnA <+> g) =<br />
((arr id) <+> f) >>> ((arr id) <+> g)<br />
<br />
which, when applied to an input x, returns all values:<br />
((id . id) x) ++ ((id . f) x) ++ ((id . g) x) ++ ((g . f) x) =<br />
x ++ (f x) ++ (g x) ++ ((g . f) x)<br />
<br />
which are all permutations of using arrows f and g.<br />
<br />
== Tutorial Meta ==<br />
The wiki file source is literate Haskell. Save the source in a file called ArrowFun.lhs to compile it (or run in GHCi).<br />
<br />
The code is adapted to GHC 6.10.1; use [http://www.haskell.org/haskellwiki/?title=Arrow_tutorial&oldid=15443] for older versions of GHC and other Haskell implementations.<br />
<br />
* Original version - Nov 19, 2006, Tim Newsham.<br />
\</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Arrow_tutorial&diff=58583Arrow tutorial2014-07-15T17:42:23Z<p>Amy de B: /* An Example */</p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Arrow]]<br />
<haskell><br />
<br />
> {-# LANGUAGE Arrows #-}<br />
> module ArrowFun where<br />
> import Control.Arrow<br />
> import Control.Category<br />
> import Prelude hiding (id,(.))<br />
<br />
</haskell><br />
<br />
== The Arrow ==<br />
Arrow a b c represents a process that takes as input something of<br />
type b and outputs something of type c.<br />
<br />
Arr builds an arrow out of a function. This function is<br />
arrow-specific. Its signature is<br />
<br />
<haskell><br />
<br />
arr :: (Arrow a) => (b -> c) -> a b c<br />
<br />
</haskell><br />
<br />
Arrow composition is achieved with (>>>). This takes two arrows<br />
and chains them together, one after another. It is also arrow-<br />
specific. Its signature is:<br />
<br />
<haskell><br />
<br />
(>>>) :: (Arrow a) => a b c -> a c d -> a b d<br />
<br />
</haskell><br />
<br />
First and second make a new arrow out of an existing arrow. They<br />
perform a transformation (given by their argument) on either<br />
the first or the second item of a pair. These definitions are<br />
arrow-specific. Their signatures are:<br />
<br />
<haskell><br />
<br />
first :: (Arrow a) => a b c -> a (b, d) (c, d)<br />
second :: (Arrow a) => a b c -> a (d, b) (d, c)<br />
<br />
</haskell><br />
<br />
First and second may seem pretty strange at first, but they'll make sense <br />
in a few minutes.<br />
<br />
That's it for the arrow-specific definitions.<br />
<br />
== A Simple Arrow ==<br />
Let's define a really simple arrow as an example. Our simple arrow is <br />
just a function mapping an input to an output. We don't really need <br />
arrows for something this simple, but we could use something this <br />
simple to explain arrows.<br />
<br />
<haskell><br />
<br />
> newtype SimpleFunc a b = SimpleFunc {<br />
> runF :: (a -> b)<br />
> }<br />
><br />
> instance Arrow SimpleFunc where<br />
> arr f = SimpleFunc f<br />
> first (SimpleFunc f) = SimpleFunc (mapFst f)<br />
> where mapFst g (a,b) = (g a, b)<br />
> second (SimpleFunc f) = SimpleFunc (mapSnd f)<br />
> where mapSnd g (a,b) = (a, g b)<br />
><br />
> instance Category SimpleFunc where<br />
> (SimpleFunc g) . (SimpleFunc f) = SimpleFunc (g . f)<br />
> id = arr id<br />
<br />
</haskell><br />
<br />
== Some Arrow Operations ==<br />
Now lets define some operations that are generic to all arrows.<br />
<br />
Split is an arrow that splits a single value into a pair of duplicate<br />
values:<br />
<br />
<haskell><br />
<br />
> split :: (Arrow a) => a b (b, b)<br />
> split = arr (\x -> (x,x))<br />
<br />
</haskell><br />
<br />
Unsplit is an arrow that takes a pair of values and combines them<br />
to return a single value:<br />
<br />
<haskell><br />
<br />
> unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d<br />
> unsplit = arr . uncurry <br />
> -- arr (\op (x,y) -> x `op` y)<br />
<br />
</haskell><br />
<br />
(***) combines two arrows into a new arrow by running the two arrows<br />
on a pair of values (one arrow on the first item of the pair and one arrow on the <br />
second item of the pair).<br />
<br />
<haskell><br />
<br />
f *** g = first f >>> second g<br />
<br />
</haskell><br />
<br />
(&&&) combines two arrows into a new arrow by running the two arrows on <br />
the same value:<br />
<br />
<haskell><br />
<br />
f &&& g = split >>> first f >>> second g<br />
-- = split >>> f *** g<br />
<br />
</haskell><br />
<br />
LiftA2 makes a new arrow that combines the output from two arrows using <br />
a binary operation. It works by splitting a value and operating on <br />
both halfs and then combining the result:<br />
<br />
<haskell><br />
<br />
> liftA2 :: (Arrow a) => (b -> c -> d) -> a e b -> a e c -> a e d<br />
> liftA2 op f g = split >>> first f >>> second g >>> unsplit op<br />
> -- = f &&& g >>> unsplit op<br />
<br />
</haskell><br />
<br />
<br />
== An Example ==<br />
Now let's build something using our simple arrow definition and<br />
some of the tools we just created. We start with two simple<br />
arrows, f and g. F halves its input and g triples its input and<br />
adds one:<br />
<br />
<haskell><br />
<br />
> f, g :: SimpleFunc Int Int<br />
> f = arr (`div` 2)<br />
> g = arr (\x -> x*3 + 1)<br />
<br />
</haskell><br />
<br />
We can combine these together using liftA2:<br />
<br />
<haskell><br />
<br />
> h :: SimpleFunc Int Int<br />
> h = liftA2 (+) f g<br />
><br />
> hOutput :: Int<br />
> hOutput = runF h 8<br />
<br />
</haskell><br />
<br />
What is h? How does it work? <br />
The process defined by h is (split >>> first f >>> second g >>> unsplit (+)).<br />
Lets work through an application of h to some value, 8:<br />
<br />
8 -> (8, 8) split<br />
(8, 8) -> (4, 8) first f (x `div` 2 of the first element)<br />
(4, 8) -> (4, 25) second g (3*x + 1 of the second element)<br />
(4, 25) -> 29 applies (+) to tuple elements.<br />
<br />
+------> f ---------+<br />
| v<br />
8 ---> (split) (unsplit (+)) ----> 29<br />
| ^<br />
+------> g ---------+<br />
<br />
so we see that h is a new arrow that when applied to 8, applies 8 to f <br />
and applies 8 to g and adds the results.<br />
<br />
We can duplicate the operation of `h` by performing each step<br />
separately:<br />
<br />
λ> split 8<br />
(8,8)<br />
λ> runF (first f) (8,8)<br />
(4,8)<br />
λ> runF (second g) (4,8)<br />
(4,25)<br />
λ> unsplit (+) (4, 25)<br />
29<br />
<br />
<br />
A lot of juggling occurred to get the plumbing right since<br />
h wasn't defined as a linear combination of arrows. GHC has<br />
a do-notation that simplifies this in a similar way to how<br />
do-notation simplifies monadic computation. The h function<br />
can be defined as:<br />
<br />
<haskell><br />
<br />
> h' :: SimpleFunc Int Int<br />
> h' = proc x -> do<br />
> fx <- f -< x<br />
> gx <- g -< x<br />
> returnA -< (fx + gx)<br />
><br />
> hOutput' :: Int<br />
> hOutput' = runF h' 8<br />
<br />
</haskell><br />
<br />
== Kleisli Arrows ==<br />
Let's move on to something a little fancier now: Kleisli arrows. <br />
A Kleisli arrow (Kleisli m a b) is the arrow (a -> m b) for all<br />
monads. It's defined in Control.Arrows similarly to our SimpleFunc:<br />
<br />
<haskell><br />
<br />
newtype Kleisli m a b = Kleisli {<br />
runKleisli :: (a -> m b) <br />
}<br />
<br />
</haskell><br />
<br />
It comes complete with its own definitions for arr, first, second and<br />
(>>>). This means that all multi-value functions (a -> [b]) are already <br />
defined as Kleisli arrows (because [] is a monad)! (>>>) performs<br />
composition, keeping track of all the multiple results. Split, (&&&)<br />
and (***) are all defined as before. So for example:<br />
<br />
<haskell><br />
<br />
> plusminus, double, h2 :: Kleisli [] Int Int<br />
> plusminus = Kleisli (\x -> [x, -x])<br />
> double = arr (* 2)<br />
> h2 = liftA2 (+) plusminus double <br />
><br />
> h2Output :: [Int]<br />
> h2Output = runKleisli h2 8<br />
<br />
</haskell><br />
<br />
== A Teaser ==<br />
Finally, here is a little teaser. There is an arrow function called<br />
returnA which returns an identity arrow. There is an ArrowPlus class <br />
that includes a zeroArrow (which for the list monad is an arrow that <br />
always returns the empty list) and a <+> operator (which takes the <br />
results from two arrows and concatenates them). We can build up <br />
some pretty interesting string transformations (the multi-valued<br />
function String -> [String]) using Kleisli arrows:<br />
<br />
<haskell><br />
<br />
> main :: IO ()<br />
> main = do<br />
> let<br />
> prepend x = arr (x ++)<br />
> append x = arr (++ x)<br />
> withId t = returnA <+> t<br />
> xform = (withId $ prepend "<") >>><br />
> (withId $ append ">") >>><br />
> (withId $ ((prepend "!") >>> (append "!")))<br />
> xs = ["test", "foobar"] >>= (runKleisli xform)<br />
> mapM_ putStrLn xs<br />
<br />
</haskell><br />
<br />
An important observation here is that<br />
f >>> g<br />
<br />
is multi-valued composition (g . f), and<br />
(withId f) >>> (withId g) =<br />
(returnA <+> f) >>> (returnA <+> g) =<br />
((arr id) <+> f) >>> ((arr id) <+> g)<br />
<br />
which, when applied to an input x, returns all values:<br />
((id . id) x) ++ ((id . f) x) ++ ((id . g) x) ++ ((g . f) x) =<br />
x ++ (f x) ++ (g x) ++ ((g . f) x)<br />
<br />
which are all permutations of using arrows f and g.<br />
<br />
== Tutorial Meta ==<br />
The wiki file source is literate Haskell. Save the source in a file called ArrowFun.lhs to compile it (or run in GHCi).<br />
<br />
The code is adapted to GHC 6.10.1; use [http://www.haskell.org/haskellwiki/?title=Arrow_tutorial&oldid=15443] for older versions of GHC and other Haskell implementations.<br />
<br />
* Original version - Nov 19, 2006, Tim Newsham.<br />
\</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Arrow_tutorial&diff=58582Arrow tutorial2014-07-15T17:42:00Z<p>Amy de B: Added a GHCi example of tracing the steps in the evaluation of h.</p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Arrow]]<br />
<haskell><br />
<br />
> {-# LANGUAGE Arrows #-}<br />
> module ArrowFun where<br />
> import Control.Arrow<br />
> import Control.Category<br />
> import Prelude hiding (id,(.))<br />
<br />
</haskell><br />
<br />
== The Arrow ==<br />
Arrow a b c represents a process that takes as input something of<br />
type b and outputs something of type c.<br />
<br />
Arr builds an arrow out of a function. This function is<br />
arrow-specific. Its signature is<br />
<br />
<haskell><br />
<br />
arr :: (Arrow a) => (b -> c) -> a b c<br />
<br />
</haskell><br />
<br />
Arrow composition is achieved with (>>>). This takes two arrows<br />
and chains them together, one after another. It is also arrow-<br />
specific. Its signature is:<br />
<br />
<haskell><br />
<br />
(>>>) :: (Arrow a) => a b c -> a c d -> a b d<br />
<br />
</haskell><br />
<br />
First and second make a new arrow out of an existing arrow. They<br />
perform a transformation (given by their argument) on either<br />
the first or the second item of a pair. These definitions are<br />
arrow-specific. Their signatures are:<br />
<br />
<haskell><br />
<br />
first :: (Arrow a) => a b c -> a (b, d) (c, d)<br />
second :: (Arrow a) => a b c -> a (d, b) (d, c)<br />
<br />
</haskell><br />
<br />
First and second may seem pretty strange at first, but they'll make sense <br />
in a few minutes.<br />
<br />
That's it for the arrow-specific definitions.<br />
<br />
== A Simple Arrow ==<br />
Let's define a really simple arrow as an example. Our simple arrow is <br />
just a function mapping an input to an output. We don't really need <br />
arrows for something this simple, but we could use something this <br />
simple to explain arrows.<br />
<br />
<haskell><br />
<br />
> newtype SimpleFunc a b = SimpleFunc {<br />
> runF :: (a -> b)<br />
> }<br />
><br />
> instance Arrow SimpleFunc where<br />
> arr f = SimpleFunc f<br />
> first (SimpleFunc f) = SimpleFunc (mapFst f)<br />
> where mapFst g (a,b) = (g a, b)<br />
> second (SimpleFunc f) = SimpleFunc (mapSnd f)<br />
> where mapSnd g (a,b) = (a, g b)<br />
><br />
> instance Category SimpleFunc where<br />
> (SimpleFunc g) . (SimpleFunc f) = SimpleFunc (g . f)<br />
> id = arr id<br />
<br />
</haskell><br />
<br />
== Some Arrow Operations ==<br />
Now lets define some operations that are generic to all arrows.<br />
<br />
Split is an arrow that splits a single value into a pair of duplicate<br />
values:<br />
<br />
<haskell><br />
<br />
> split :: (Arrow a) => a b (b, b)<br />
> split = arr (\x -> (x,x))<br />
<br />
</haskell><br />
<br />
Unsplit is an arrow that takes a pair of values and combines them<br />
to return a single value:<br />
<br />
<haskell><br />
<br />
> unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d<br />
> unsplit = arr . uncurry <br />
> -- arr (\op (x,y) -> x `op` y)<br />
<br />
</haskell><br />
<br />
(***) combines two arrows into a new arrow by running the two arrows<br />
on a pair of values (one arrow on the first item of the pair and one arrow on the <br />
second item of the pair).<br />
<br />
<haskell><br />
<br />
f *** g = first f >>> second g<br />
<br />
</haskell><br />
<br />
(&&&) combines two arrows into a new arrow by running the two arrows on <br />
the same value:<br />
<br />
<haskell><br />
<br />
f &&& g = split >>> first f >>> second g<br />
-- = split >>> f *** g<br />
<br />
</haskell><br />
<br />
LiftA2 makes a new arrow that combines the output from two arrows using <br />
a binary operation. It works by splitting a value and operating on <br />
both halfs and then combining the result:<br />
<br />
<haskell><br />
<br />
> liftA2 :: (Arrow a) => (b -> c -> d) -> a e b -> a e c -> a e d<br />
> liftA2 op f g = split >>> first f >>> second g >>> unsplit op<br />
> -- = f &&& g >>> unsplit op<br />
<br />
</haskell><br />
<br />
<br />
== An Example ==<br />
Now let's build something using our simple arrow definition and<br />
some of the tools we just created. We start with two simple<br />
arrows, f and g. F halves its input and g triples its input and<br />
adds one:<br />
<br />
<haskell><br />
<br />
> f, g :: SimpleFunc Int Int<br />
> f = arr (`div` 2)<br />
> g = arr (\x -> x*3 + 1)<br />
<br />
</haskell><br />
<br />
We can combine these together using liftA2:<br />
<br />
<haskell><br />
<br />
> h :: SimpleFunc Int Int<br />
> h = liftA2 (+) f g<br />
><br />
> hOutput :: Int<br />
> hOutput = runF h 8<br />
<br />
</haskell><br />
<br />
What is h? How does it work? <br />
The process defined by h is (split >>> first f >>> second g >>> unsplit (+)).<br />
Lets work through an application of h to some value, 8:<br />
<br />
8 -> (8, 8) split<br />
(8, 8) -> (4, 8) first f (x `div` 2 of the first element)<br />
(4, 8) -> (4, 25) second g (3*x + 1 of the second element)<br />
(4, 25) -> 29 applies (+) to tuple elements.<br />
<br />
+------> f ---------+<br />
| v<br />
8 ---> (split) (unsplit (+)) ----> 29<br />
| ^<br />
+------> g ---------+<br />
<br />
so we see that h is a new arrow that when applied to 8, applies 8 to f <br />
and applies 8 to g and adds the results.<br />
<br />
We can duplicate the operation of `h` by performing each step<br />
separately.<br />
<br />
λ> split 8<br />
(8,8)<br />
λ> runF (first f) (8,8)<br />
(4,8)<br />
λ> runF (second g) (4,8)<br />
(4,25)<br />
λ> unsplit (+) (4, 25)<br />
29<br />
<br />
<br />
A lot of juggling occurred to get the plumbing right since<br />
h wasn't defined as a linear combination of arrows. GHC has<br />
a do-notation that simplifies this in a similar way to how<br />
do-notation simplifies monadic computation. The h function<br />
can be defined as:<br />
<br />
<haskell><br />
<br />
> h' :: SimpleFunc Int Int<br />
> h' = proc x -> do<br />
> fx <- f -< x<br />
> gx <- g -< x<br />
> returnA -< (fx + gx)<br />
><br />
> hOutput' :: Int<br />
> hOutput' = runF h' 8<br />
<br />
</haskell><br />
<br />
== Kleisli Arrows ==<br />
Let's move on to something a little fancier now: Kleisli arrows. <br />
A Kleisli arrow (Kleisli m a b) is the arrow (a -> m b) for all<br />
monads. It's defined in Control.Arrows similarly to our SimpleFunc:<br />
<br />
<haskell><br />
<br />
newtype Kleisli m a b = Kleisli {<br />
runKleisli :: (a -> m b) <br />
}<br />
<br />
</haskell><br />
<br />
It comes complete with its own definitions for arr, first, second and<br />
(>>>). This means that all multi-value functions (a -> [b]) are already <br />
defined as Kleisli arrows (because [] is a monad)! (>>>) performs<br />
composition, keeping track of all the multiple results. Split, (&&&)<br />
and (***) are all defined as before. So for example:<br />
<br />
<haskell><br />
<br />
> plusminus, double, h2 :: Kleisli [] Int Int<br />
> plusminus = Kleisli (\x -> [x, -x])<br />
> double = arr (* 2)<br />
> h2 = liftA2 (+) plusminus double <br />
><br />
> h2Output :: [Int]<br />
> h2Output = runKleisli h2 8<br />
<br />
</haskell><br />
<br />
== A Teaser ==<br />
Finally, here is a little teaser. There is an arrow function called<br />
returnA which returns an identity arrow. There is an ArrowPlus class <br />
that includes a zeroArrow (which for the list monad is an arrow that <br />
always returns the empty list) and a <+> operator (which takes the <br />
results from two arrows and concatenates them). We can build up <br />
some pretty interesting string transformations (the multi-valued<br />
function String -> [String]) using Kleisli arrows:<br />
<br />
<haskell><br />
<br />
> main :: IO ()<br />
> main = do<br />
> let<br />
> prepend x = arr (x ++)<br />
> append x = arr (++ x)<br />
> withId t = returnA <+> t<br />
> xform = (withId $ prepend "<") >>><br />
> (withId $ append ">") >>><br />
> (withId $ ((prepend "!") >>> (append "!")))<br />
> xs = ["test", "foobar"] >>= (runKleisli xform)<br />
> mapM_ putStrLn xs<br />
<br />
</haskell><br />
<br />
An important observation here is that<br />
f >>> g<br />
<br />
is multi-valued composition (g . f), and<br />
(withId f) >>> (withId g) =<br />
(returnA <+> f) >>> (returnA <+> g) =<br />
((arr id) <+> f) >>> ((arr id) <+> g)<br />
<br />
which, when applied to an input x, returns all values:<br />
((id . id) x) ++ ((id . f) x) ++ ((id . g) x) ++ ((g . f) x) =<br />
x ++ (f x) ++ (g x) ++ ((g . f) x)<br />
<br />
which are all permutations of using arrows f and g.<br />
<br />
== Tutorial Meta ==<br />
The wiki file source is literate Haskell. Save the source in a file called ArrowFun.lhs to compile it (or run in GHCi).<br />
<br />
The code is adapted to GHC 6.10.1; use [http://www.haskell.org/haskellwiki/?title=Arrow_tutorial&oldid=15443] for older versions of GHC and other Haskell implementations.<br />
<br />
* Original version - Nov 19, 2006, Tim Newsham.<br />
\</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Arrow_tutorial&diff=58581Arrow tutorial2014-07-15T17:09:21Z<p>Amy de B: -farrows is deprecated, use language pragma Arrows instead</p>
<hr />
<div>[[Category:Tutorials]]<br />
[[Category:Arrow]]<br />
<haskell><br />
<br />
> {-# LANGUAGE Arrows #-}<br />
> module ArrowFun where<br />
> import Control.Arrow<br />
> import Control.Category<br />
> import Prelude hiding (id,(.))<br />
<br />
</haskell><br />
<br />
== The Arrow ==<br />
Arrow a b c represents a process that takes as input something of<br />
type b and outputs something of type c.<br />
<br />
Arr builds an arrow out of a function. This function is<br />
arrow-specific. Its signature is<br />
<br />
<haskell><br />
<br />
arr :: (Arrow a) => (b -> c) -> a b c<br />
<br />
</haskell><br />
<br />
Arrow composition is achieved with (>>>). This takes two arrows<br />
and chains them together, one after another. It is also arrow-<br />
specific. Its signature is:<br />
<br />
<haskell><br />
<br />
(>>>) :: (Arrow a) => a b c -> a c d -> a b d<br />
<br />
</haskell><br />
<br />
First and second make a new arrow out of an existing arrow. They<br />
perform a transformation (given by their argument) on either<br />
the first or the second item of a pair. These definitions are<br />
arrow-specific. Their signatures are:<br />
<br />
<haskell><br />
<br />
first :: (Arrow a) => a b c -> a (b, d) (c, d)<br />
second :: (Arrow a) => a b c -> a (d, b) (d, c)<br />
<br />
</haskell><br />
<br />
First and second may seem pretty strange at first, but they'll make sense <br />
in a few minutes.<br />
<br />
That's it for the arrow-specific definitions.<br />
<br />
== A Simple Arrow ==<br />
Let's define a really simple arrow as an example. Our simple arrow is <br />
just a function mapping an input to an output. We don't really need <br />
arrows for something this simple, but we could use something this <br />
simple to explain arrows.<br />
<br />
<haskell><br />
<br />
> newtype SimpleFunc a b = SimpleFunc {<br />
> runF :: (a -> b)<br />
> }<br />
><br />
> instance Arrow SimpleFunc where<br />
> arr f = SimpleFunc f<br />
> first (SimpleFunc f) = SimpleFunc (mapFst f)<br />
> where mapFst g (a,b) = (g a, b)<br />
> second (SimpleFunc f) = SimpleFunc (mapSnd f)<br />
> where mapSnd g (a,b) = (a, g b)<br />
><br />
> instance Category SimpleFunc where<br />
> (SimpleFunc g) . (SimpleFunc f) = SimpleFunc (g . f)<br />
> id = arr id<br />
<br />
</haskell><br />
<br />
== Some Arrow Operations ==<br />
Now lets define some operations that are generic to all arrows.<br />
<br />
Split is an arrow that splits a single value into a pair of duplicate<br />
values:<br />
<br />
<haskell><br />
<br />
> split :: (Arrow a) => a b (b, b)<br />
> split = arr (\x -> (x,x))<br />
<br />
</haskell><br />
<br />
Unsplit is an arrow that takes a pair of values and combines them<br />
to return a single value:<br />
<br />
<haskell><br />
<br />
> unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d<br />
> unsplit = arr . uncurry <br />
> -- arr (\op (x,y) -> x `op` y)<br />
<br />
</haskell><br />
<br />
(***) combines two arrows into a new arrow by running the two arrows<br />
on a pair of values (one arrow on the first item of the pair and one arrow on the <br />
second item of the pair).<br />
<br />
<haskell><br />
<br />
f *** g = first f >>> second g<br />
<br />
</haskell><br />
<br />
(&&&) combines two arrows into a new arrow by running the two arrows on <br />
the same value:<br />
<br />
<haskell><br />
<br />
f &&& g = split >>> first f >>> second g<br />
-- = split >>> f *** g<br />
<br />
</haskell><br />
<br />
LiftA2 makes a new arrow that combines the output from two arrows using <br />
a binary operation. It works by splitting a value and operating on <br />
both halfs and then combining the result:<br />
<br />
<haskell><br />
<br />
> liftA2 :: (Arrow a) => (b -> c -> d) -> a e b -> a e c -> a e d<br />
> liftA2 op f g = split >>> first f >>> second g >>> unsplit op<br />
> -- = f &&& g >>> unsplit op<br />
<br />
</haskell><br />
<br />
<br />
== An Example ==<br />
Now let's build something using our simple arrow definition and<br />
some of the tools we just created. We start with two simple<br />
arrows, f and g. F halves its input and g triples its input and<br />
adds one:<br />
<br />
<haskell><br />
<br />
> f, g :: SimpleFunc Int Int<br />
> f = arr (`div` 2)<br />
> g = arr (\x -> x*3 + 1)<br />
<br />
</haskell><br />
<br />
We can combine these together using liftA2:<br />
<br />
<haskell><br />
<br />
> h :: SimpleFunc Int Int<br />
> h = liftA2 (+) f g<br />
><br />
> hOutput :: Int<br />
> hOutput = runF h 8<br />
<br />
</haskell><br />
<br />
What is h? How does it work? <br />
The process defined by h is (split >>> first f >>> second g >>> unsplit (+)).<br />
Lets work through an application of h to some value, 8:<br />
<br />
8 -> (8, 8) split<br />
(8, 8) -> (4, 8) first f (x `div` 2 of the first element)<br />
(4, 8) -> (4, 25) second g (3*x + 1 of the second element)<br />
(4, 25) -> 29 applies (+) to tuple elements.<br />
<br />
+------> f ---------+<br />
| v<br />
8 ---> (split) (unsplit (+)) ----> 29<br />
| ^<br />
+------> g ---------+<br />
<br />
so we see that h is a new arrow that when applied to 8, applies 8 to f <br />
and applies 8 to g and adds the results.<br />
<br />
A lot of juggling occurred to get the plumbing right since<br />
h wasn't defined as a linear combination of arrows. GHC has<br />
a do-notation that simplifies this in a similar way to how<br />
do-notation simplifies monadic computation. The h function<br />
can be defined as:<br />
<br />
<haskell><br />
<br />
> h' :: SimpleFunc Int Int<br />
> h' = proc x -> do<br />
> fx <- f -< x<br />
> gx <- g -< x<br />
> returnA -< (fx + gx)<br />
><br />
> hOutput' :: Int<br />
> hOutput' = runF h' 8<br />
<br />
</haskell><br />
<br />
== Kleisli Arrows ==<br />
Let's move on to something a little fancier now: Kleisli arrows. <br />
A Kleisli arrow (Kleisli m a b) is the arrow (a -> m b) for all<br />
monads. It's defined in Control.Arrows similarly to our SimpleFunc:<br />
<br />
<haskell><br />
<br />
newtype Kleisli m a b = Kleisli {<br />
runKleisli :: (a -> m b) <br />
}<br />
<br />
</haskell><br />
<br />
It comes complete with its own definitions for arr, first, second and<br />
(>>>). This means that all multi-value functions (a -> [b]) are already <br />
defined as Kleisli arrows (because [] is a monad)! (>>>) performs<br />
composition, keeping track of all the multiple results. Split, (&&&)<br />
and (***) are all defined as before. So for example:<br />
<br />
<haskell><br />
<br />
> plusminus, double, h2 :: Kleisli [] Int Int<br />
> plusminus = Kleisli (\x -> [x, -x])<br />
> double = arr (* 2)<br />
> h2 = liftA2 (+) plusminus double <br />
><br />
> h2Output :: [Int]<br />
> h2Output = runKleisli h2 8<br />
<br />
</haskell><br />
<br />
== A Teaser ==<br />
Finally, here is a little teaser. There is an arrow function called<br />
returnA which returns an identity arrow. There is an ArrowPlus class <br />
that includes a zeroArrow (which for the list monad is an arrow that <br />
always returns the empty list) and a <+> operator (which takes the <br />
results from two arrows and concatenates them). We can build up <br />
some pretty interesting string transformations (the multi-valued<br />
function String -> [String]) using Kleisli arrows:<br />
<br />
<haskell><br />
<br />
> main :: IO ()<br />
> main = do<br />
> let<br />
> prepend x = arr (x ++)<br />
> append x = arr (++ x)<br />
> withId t = returnA <+> t<br />
> xform = (withId $ prepend "<") >>><br />
> (withId $ append ">") >>><br />
> (withId $ ((prepend "!") >>> (append "!")))<br />
> xs = ["test", "foobar"] >>= (runKleisli xform)<br />
> mapM_ putStrLn xs<br />
<br />
</haskell><br />
<br />
An important observation here is that<br />
f >>> g<br />
<br />
is multi-valued composition (g . f), and<br />
(withId f) >>> (withId g) =<br />
(returnA <+> f) >>> (returnA <+> g) =<br />
((arr id) <+> f) >>> ((arr id) <+> g)<br />
<br />
which, when applied to an input x, returns all values:<br />
((id . id) x) ++ ((id . f) x) ++ ((id . g) x) ++ ((g . f) x) =<br />
x ++ (f x) ++ (g x) ++ ((g . f) x)<br />
<br />
which are all permutations of using arrows f and g.<br />
<br />
== Tutorial Meta ==<br />
The wiki file source is literate Haskell. Save the source in a file called ArrowFun.lhs to compile it (or run in GHCi).<br />
<br />
The code is adapted to GHC 6.10.1; use [http://www.haskell.org/haskellwiki/?title=Arrow_tutorial&oldid=15443] for older versions of GHC and other Haskell implementations.<br />
<br />
* Original version - Nov 19, 2006, Tim Newsham.<br />
\</div>Amy de Bhttps://wiki.haskell.org/index.php?title=GHC.Generics&diff=56414GHC.Generics2013-07-17T09:30:00Z<p>Amy de B: /* Complete working example */</p>
<hr />
<div>GHC 7.2 includes improved support for ''datatype-generic programming'' through two new features, enabled with two new flags: <tt>DeriveGeneric</tt> and <tt>DefaultSignatures</tt>. We show how this all works in this page, starting with a detailed example.<br />
<br />
Since this is a fresh new feature, it is possible that you will run into bugs when using it. If so, please<br />
[http://hackage.haskell.org/trac/ghc/wiki/ReportABug report them]!<br />
<br />
== Example: serialization ==<br />
<br />
Suppose you are writing a class for serialization of data. You have a type <hask>Bit</hask> representing bits, and a class <hask>Serialize</hask>:<br />
<br />
<haskell><br />
data Bit = O | I<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
</haskell><br />
<br />
You might have written some instances already:<br />
<br />
<haskell><br />
instance Serialize Int where<br />
put i = serializeInt i<br />
<br />
instance Serialize a => Serialize [a] where<br />
put [] = []<br />
put (h:t) = put h ++ put t<br />
</haskell><br />
<br />
A user of your library, however, will have his own datatypes, like:<br />
<br />
<haskell><br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
</haskell><br />
<br />
He will have to specify an <hask>instance Serialize (UserTree a) where ...</hask> himself. This, however, is tedious, especially because most instances will probably be rather trivial, and should be derived automatically.<br />
<br />
It is here that generic programming can help you. If you are familiar with [http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB SYB] you could use it at this stage, but now we'll see how to do this with the new features of GHC 7.2.<br />
<br />
=== Generic serialization ===<br />
<br />
First you have to tell the compiler how to serialize any datatype, in general. Since Haskell datatypes have a regular structure, this means you can just explain how to serialize a few basic datatypes.<br />
<br />
==== Representation types ====<br />
<br />
We can represent most Haskell datatypes using only the following primitive types:<br />
<br />
<haskell><br />
-- | Unit: used for constructors without arguments<br />
data U1 p = U1<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
newtype K1 i c p = K1 { unK1 :: c }<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
newtype M1 i c f p = M1 { unM1 :: f p }<br />
<br />
-- | Sums: encode choice between constructors<br />
infixr 5 :+:<br />
data (:+:) f g p = L1 (f p) | R1 (g p)<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
infixr 6 :*:<br />
data (:*:) f g p = f p :*: g p<br />
</haskell><br />
<br />
For starters, try to ignore the <tt>p</tt> parameter in all types; it's there just for future compatibility. The easiest way to understand how you can use these types to represent others is to see an example. Let's represent the <hask>UserTree</hask> type shown before:<br />
<br />
<haskell><br />
type RepUserTree a =<br />
-- A UserTree is either a Leaf, which has no arguments<br />
U1<br />
-- ... or it is a Node, which has three arguments that we put in a product<br />
:+: a :*: UserTree a :*: UserTree a<br />
</haskell><br />
<br />
Simple, right? Different constructors become alternatives of a sum, and multiple arguments become products. In fact, we want to have some more information in the representation, like datatype and constructor names, and to know if a product argument is a parameter or a type. We use the other primitives for this, and the representation looks more like:<br />
<br />
<haskell><br />
type RealRepUserTree a =<br />
-- Information about the datatype<br />
M1 D Data_UserTree (<br />
-- Leaf, with information about the constructor<br />
M1 C Con_Leaf U1<br />
-- Node, with information about the constructor<br />
:+: M1 C Con_Node (<br />
-- Constructor argument, which could have information<br />
-- about a record selector label<br />
M1 S NoSelector (<br />
-- Argument, tagged with P because it is a parameter<br />
K1 P a)<br />
-- Another argument, tagged with R because it is <br />
-- a recursive occurrence of a type<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
-- Idem<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
))<br />
</haskell><br />
<br />
A bit more complicated, but essentially the same. Datatypes like <hask>Data_UserTree</hask> are empty datatypes used only for providing meta-information in the representation; you don't have to worry much about them for now. Also, GHC generates these representations for you automatically, so you should never have to define them yourself! All of this is explained in much more detail in Section 2.1. of [http://dreixel.net/research/pdf/gdmh.pdf the original paper describing the new generic deriving mechanism].<br />
<br />
==== A generic function ====<br />
<br />
Since GHC can represent user types using only those primitive types, all you have to do is to tell GHC how to serialize each of the individual primitive types. The best way to do that is to create a new type class:<br />
<br />
<haskell><br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
</haskell><br />
<br />
This class looks very much like the original <hask>Serialize</hask> class, just that the type argument is of kind <hask>* -> *</hask>, since our generic representation types have this <tt>p</tt> parameter lying around. Now we need to give instances for each of the basic types. For units there's nothing to serialize:<br />
<br />
<haskell><br />
instance GSerialize U1 where<br />
gput U1 = []<br />
</haskell><br />
<br />
The serialization of multiple arguments is simply the concatenation of each of the individual serializations:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
</haskell><br />
<br />
The case for sums is the most interesting, as we have to record which alternative we are in. We will use a 0 for left injections and a 1 for right injections:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
</haskell><br />
<br />
We don't need to encode the meta-information, so we just go over it recursively :<br />
<br />
<haskell><br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
</haskell><br />
<br />
Finally, we're only left with the arguments. For these we will just use our first class, <hask>Serialize</hask>, again:<br />
<br />
<haskell><br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
</haskell><br />
<br />
So, if a user datatype has a parameter which is instantiated to <hask>Int</hask>, at this stage we will use the library instance for <hask>Serialize Int</hask>.<br />
<br />
==== Default implementations ====<br />
<br />
We've seen how to represent user types generically, and how to define functions on representation types. However, we still have to tie these two together, explaining how to convert user types to their representation and then applying the generic function.<br />
<br />
The representation <hask>RepUserTree</hask> we have seen earlier is only one component of the representation; we also need functions to convert to and from the user datatype into the representation. For that we use another type class:<br />
<br />
<haskell><br />
class Generic a where<br />
-- Encode the representation of a user datatype<br />
type Rep a :: * -> *<br />
-- Convert from the datatype to its representation<br />
from :: a -> (Rep a) x<br />
-- Convert from the representation to the datatype<br />
to :: (Rep a) x -> a<br />
</haskell><br />
<br />
So, for the <hask>UserTree</hask> datatype shown before, GHC generates the following instance:<br />
<br />
<haskell><br />
instance Generic (UserTree a) where<br />
type Rep (UserTree a) = RepUserTree a<br />
<br />
from Leaf = L1 U1<br />
from (Node a l r) = R1 (a :*: l :*: r)<br />
<br />
to (L1 U1) = Leaf<br />
to (R1 (a :*: l :*: r)) = Node a l r<br />
</haskell><br />
<br />
(Note that we are using the simpler representation <hask>RepUserTree</hask> instead of the real representation <hask>RealRepUserTree</hask>, just for simplicity.)<br />
<br />
Equipped with a <hask>Generic</hask> instance, we are ready to tell the compiler how it can serialize any representable type:<br />
<br />
<haskell><br />
putDefault :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
putDefault a = gput (from a)<br />
</haskell><br />
<br />
The type of <hask>putDefault</hask> says that we can serialize any <tt>a</tt> into a list of bits, as long as that <tt>a</tt> is <hask>Generic</hask>, and its representation <hask>Rep a</hask> has a <hask>GSerialize</hask> instance. The implementation is very simple: first convert the value to its representation using <hask>from</hask>, and then call <hask>gput</hask> on that representation.<br />
<br />
However, we still have to write a <hask>Serialize</hask> instance for the user dataype:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a) where<br />
put = putDefault<br />
</haskell><br />
<br />
=== Using GHC's new features ===<br />
<br />
What we have seen so far could all already be done, at the cost of writing a lot of boilerplate code yourself (or spending hours writing [[Template Haskell]] code to do it for you). Now we'll see how the new features of GHC can help you.<br />
<br />
==== Deriving representations ====<br />
<br />
The <hask>Generic</hask> class, and all the representation types, come with GHC in the <tt>GHC.Generics</tt> module. GHC can also derive <hask>Generic</hask> for user types, so all the user has to do is:<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveGeneric #-}<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving Generic<br />
</haskell><br />
<br />
(Standlone deriving also works fine, and you can use it for types you have not defined yourself, but are imported from somewhere else.) You will need the new <tt>DeriveGeneric</tt> language pragma.<br />
<br />
==== More general default methods ====<br />
<br />
We don't want the user to have to write the <hask>instance Serialize (UserTree a)</hask> himself, since most of the times it will just be <hask>putDefault</hask>. However, we cannot make <hask>putDefault</hask> the default implementation of the <hask>put</hask> method, because that would require adding the <hask>(Generic a, GSerialize (Rep a))</hask> constraint to the class head. This would restrict the ability to give ad-hoc instances for types that are not representable, for instance.<br />
<br />
We solved this by allowing the user to give a different signature for default methods:<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures #-}<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
</haskell><br />
<br />
With the new language pragma <tt>DefaultSignatures</tt>, GHC allows you to put the keyword <hask>default</hask> before a (new) type signature for a method inside a class declaration. If you give such a default type signature, then you have to provide a default method implementation, which will be type-checked using the default signature, and not the original one.<br />
<br />
Now the user can simply write:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
GHC fills out the implementation for <hask>put</hask> using the default method. It will type-check correctly because we have a <hask>Generic</hask> instance for <hask>UserTree</hask>, and <hask>GSerialize</hask> instances for all the representation types.<br />
<br />
=== Complete working example ===<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures, DeriveGeneric, TypeOperators, FlexibleContexts #-}<br />
<br />
import GHC.Generics<br />
import Data.Bits<br />
<br />
<br />
data Bit = O | I deriving Show<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
<br />
get :: [Bit] -> (a, [Bit])<br />
<br />
default get :: (Generic a, GSerialize (Rep a)) => [Bit] -> (a, [Bit])<br />
get xs = (to x, xs')<br />
where (x, xs') = gget xs<br />
<br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
gget :: [Bit] -> (f a, [Bit])<br />
<br />
-- | Unit: used for constructors without arguments<br />
instance GSerialize U1 where<br />
gput U1 = []<br />
gget xs = (U1, xs)<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
gget xs = (a :*: b, xs'')<br />
where (a, xs') = gget xs<br />
(b, xs'') = gget xs'<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
gget (O:xs) = (L1 x, xs')<br />
where (x, xs') = gget xs<br />
gget (I:xs) = (R1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Sums: encode choice between constructors<br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
gget xs = (M1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
gget xs = (K1 x, xs')<br />
where (x, xs') = get xs<br />
<br />
instance Serialize Bool where<br />
put True = [I]<br />
put False = [O]<br />
get (I:xs) = (True, xs)<br />
get (O:xs) = (False, xs)<br />
<br />
--<br />
-- Try it out. (Normally this would be in a separate module.)<br />
--<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving (Generic, Show)<br />
<br />
instance (Serialize a) => Serialize (UserTree a)<br />
<br />
main = do<br />
let xs = put True<br />
print (fst . get $ xs :: Bool)<br />
let ys = put (Leaf :: UserTree Bool)<br />
print (fst . get $ ys :: UserTree Bool)<br />
let zs = put (Node False Leaf Leaf :: UserTree Bool)<br />
print (fst . get $ zs :: UserTree Bool)<br />
</haskell><br />
<br />
== Different perspectives ==<br />
<br />
We outline the changes introduced in 7.2 regarding support for generic programming from the perspective of three different types of users: the end-user, the generic programmer, and the GHC hacker.<br />
<br />
=== The end-user ===<br />
<br />
If you know nothing about generic programming and would like to keep it that way, then you will be pleased to know that using generics in GHC 7.2 is easier than ever. As soon as you encounter a class with a default signature (like <tt>Serialize</tt> above), you will be able to give empty instances for your datatypes, like this:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
You will need to add a <hask>deriving Generic</hask> clause to each datatype that you want to have generic implementations for. You might have datatypes that use other datatypes, and you might need <tt>Generic</tt> instances for those too. In that case, you can import the module where the datatype is defined and give a standalone deriving <tt>Generic</tt> instance. In either case, you will need the <tt>-XDeriveGeneric</tt> flag.<br />
<br />
=== The generic programmer ===<br />
<br />
If you are a library author and are eager to make your classes easy to instantiate by your users, then you should invest some time in defining instances for each of the representation types of <tt>GHC.Generics</tt> and defining a generic default method. See the example for <tt>Serialize</tt> above, and the [http://dreixel.net/research/pdf/gdmh.pdf original paper] for many other examples (but make sure to check the [[#Changes from the paper|changes from the paper]]).<br />
<br />
=== The GHC hacker ===<br />
<br />
If you are working on the GHC source code, you might find it useful to know what kind of changes were made. There is a [http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving Trac wiki page] with a lower-level overview of things and also keeping track of what still needs to be done.<br />
<br />
== Changes from the paper ==<br />
<br />
In the [http://dreixel.net/research/pdf/gdmh.pdf paper] we describe the implementation in [http://www.cs.uu.nl/wiki/UHC UHC]. The implementation in GHC is slightly different:<br />
<br />
* <tt>Representable0</tt> and <tt>Representable1</tt> have become <tt>Generic</tt> and <tt>Generic1</tt>, respectively. <tt>from0</tt>, <tt>to0</tt>, and <tt>Rep0</tt> also lost the <tt>0</tt> at the end of their names.<br />
<br />
* We are using type families, so the <tt>Generic</tt> and <tt>Generic1</tt> type classes have only one type argument. So, in GHC the classes look like what we describe in the "Avoiding extensions" part of Section 2.3 of the paper. This change affects only a generic function writer, and not a generic function user.<br />
<br />
* Default definitions (Section 3.3) work differently. In GHC we don't use a <tt>DERIVABLE</tt> pragma; instead, a type class can declare a ''generic default method'', which is akin to a standard default method, but includes a default type signature. This removes the need for a separate default definition and a pragma. For example, the <tt>Encode</tt> class of Section 3.1 is now:<br />
<haskell><br />
class Encode a where<br />
encode :: a -> [Bit]<br />
default encode :: (Generic a, Encode1 (Rep a)) => a -> [Bit]<br />
encode = encode1 . from<br />
</haskell><br />
<br />
* To derive generic functionality to a user type, the user no longer uses <hask>deriving instance</hask> (Section 4.6.1). Instead, the user gives an instance without defining the method; GHC then uses the generic default. For instance:<br />
<haskell><br />
instance Encode [a] -- works if there is an instance Generic [a]<br />
</haskell><br />
<br />
== Limitations ==<br />
<br />
We cannot derive <tt>Generic</tt> instances for:<br />
* Datatypes with a context;<br />
* Existentially-quantified datatypes;<br />
* GADTs.<br />
<br />
<br />
[[Category:GHC]]<br />
[[Category:Language extensions]]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=GHC.Generics&diff=56413GHC.Generics2013-07-17T09:25:51Z<p>Amy de B: Moved the example to a different section</p>
<hr />
<div>GHC 7.2 includes improved support for ''datatype-generic programming'' through two new features, enabled with two new flags: <tt>DeriveGeneric</tt> and <tt>DefaultSignatures</tt>. We show how this all works in this page, starting with a detailed example.<br />
<br />
Since this is a fresh new feature, it is possible that you will run into bugs when using it. If so, please<br />
[http://hackage.haskell.org/trac/ghc/wiki/ReportABug report them]!<br />
<br />
== Example: serialization ==<br />
<br />
Suppose you are writing a class for serialization of data. You have a type <hask>Bit</hask> representing bits, and a class <hask>Serialize</hask>:<br />
<br />
<haskell><br />
data Bit = O | I<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
</haskell><br />
<br />
You might have written some instances already:<br />
<br />
<haskell><br />
instance Serialize Int where<br />
put i = serializeInt i<br />
<br />
instance Serialize a => Serialize [a] where<br />
put [] = []<br />
put (h:t) = put h ++ put t<br />
</haskell><br />
<br />
A user of your library, however, will have his own datatypes, like:<br />
<br />
<haskell><br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
</haskell><br />
<br />
He will have to specify an <hask>instance Serialize (UserTree a) where ...</hask> himself. This, however, is tedious, especially because most instances will probably be rather trivial, and should be derived automatically.<br />
<br />
It is here that generic programming can help you. If you are familiar with [http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB SYB] you could use it at this stage, but now we'll see how to do this with the new features of GHC 7.2.<br />
<br />
=== Generic serialization ===<br />
<br />
First you have to tell the compiler how to serialize any datatype, in general. Since Haskell datatypes have a regular structure, this means you can just explain how to serialize a few basic datatypes.<br />
<br />
==== Representation types ====<br />
<br />
We can represent most Haskell datatypes using only the following primitive types:<br />
<br />
<haskell><br />
-- | Unit: used for constructors without arguments<br />
data U1 p = U1<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
newtype K1 i c p = K1 { unK1 :: c }<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
newtype M1 i c f p = M1 { unM1 :: f p }<br />
<br />
-- | Sums: encode choice between constructors<br />
infixr 5 :+:<br />
data (:+:) f g p = L1 (f p) | R1 (g p)<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
infixr 6 :*:<br />
data (:*:) f g p = f p :*: g p<br />
</haskell><br />
<br />
For starters, try to ignore the <tt>p</tt> parameter in all types; it's there just for future compatibility. The easiest way to understand how you can use these types to represent others is to see an example. Let's represent the <hask>UserTree</hask> type shown before:<br />
<br />
<haskell><br />
type RepUserTree a =<br />
-- A UserTree is either a Leaf, which has no arguments<br />
U1<br />
-- ... or it is a Node, which has three arguments that we put in a product<br />
:+: a :*: UserTree a :*: UserTree a<br />
</haskell><br />
<br />
Simple, right? Different constructors become alternatives of a sum, and multiple arguments become products. In fact, we want to have some more information in the representation, like datatype and constructor names, and to know if a product argument is a parameter or a type. We use the other primitives for this, and the representation looks more like:<br />
<br />
<haskell><br />
type RealRepUserTree a =<br />
-- Information about the datatype<br />
M1 D Data_UserTree (<br />
-- Leaf, with information about the constructor<br />
M1 C Con_Leaf U1<br />
-- Node, with information about the constructor<br />
:+: M1 C Con_Node (<br />
-- Constructor argument, which could have information<br />
-- about a record selector label<br />
M1 S NoSelector (<br />
-- Argument, tagged with P because it is a parameter<br />
K1 P a)<br />
-- Another argument, tagged with R because it is <br />
-- a recursive occurrence of a type<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
-- Idem<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
))<br />
</haskell><br />
<br />
A bit more complicated, but essentially the same. Datatypes like <hask>Data_UserTree</hask> are empty datatypes used only for providing meta-information in the representation; you don't have to worry much about them for now. Also, GHC generates these representations for you automatically, so you should never have to define them yourself! All of this is explained in much more detail in Section 2.1. of [http://dreixel.net/research/pdf/gdmh.pdf the original paper describing the new generic deriving mechanism].<br />
<br />
==== A generic function ====<br />
<br />
Since GHC can represent user types using only those primitive types, all you have to do is to tell GHC how to serialize each of the individual primitive types. The best way to do that is to create a new type class:<br />
<br />
<haskell><br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
</haskell><br />
<br />
This class looks very much like the original <hask>Serialize</hask> class, just that the type argument is of kind <hask>* -> *</hask>, since our generic representation types have this <tt>p</tt> parameter lying around. Now we need to give instances for each of the basic types. For units there's nothing to serialize:<br />
<br />
<haskell><br />
instance GSerialize U1 where<br />
gput U1 = []<br />
</haskell><br />
<br />
The serialization of multiple arguments is simply the concatenation of each of the individual serializations:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
</haskell><br />
<br />
The case for sums is the most interesting, as we have to record which alternative we are in. We will use a 0 for left injections and a 1 for right injections:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
</haskell><br />
<br />
We don't need to encode the meta-information, so we just go over it recursively :<br />
<br />
<haskell><br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
</haskell><br />
<br />
Finally, we're only left with the arguments. For these we will just use our first class, <hask>Serialize</hask>, again:<br />
<br />
<haskell><br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
</haskell><br />
<br />
So, if a user datatype has a parameter which is instantiated to <hask>Int</hask>, at this stage we will use the library instance for <hask>Serialize Int</hask>.<br />
<br />
==== Default implementations ====<br />
<br />
We've seen how to represent user types generically, and how to define functions on representation types. However, we still have to tie these two together, explaining how to convert user types to their representation and then applying the generic function.<br />
<br />
The representation <hask>RepUserTree</hask> we have seen earlier is only one component of the representation; we also need functions to convert to and from the user datatype into the representation. For that we use another type class:<br />
<br />
<haskell><br />
class Generic a where<br />
-- Encode the representation of a user datatype<br />
type Rep a :: * -> *<br />
-- Convert from the datatype to its representation<br />
from :: a -> (Rep a) x<br />
-- Convert from the representation to the datatype<br />
to :: (Rep a) x -> a<br />
</haskell><br />
<br />
So, for the <hask>UserTree</hask> datatype shown before, GHC generates the following instance:<br />
<br />
<haskell><br />
instance Generic (UserTree a) where<br />
type Rep (UserTree a) = RepUserTree a<br />
<br />
from Leaf = L1 U1<br />
from (Node a l r) = R1 (a :*: l :*: r)<br />
<br />
to (L1 U1) = Leaf<br />
to (R1 (a :*: l :*: r)) = Node a l r<br />
</haskell><br />
<br />
(Note that we are using the simpler representation <hask>RepUserTree</hask> instead of the real representation <hask>RealRepUserTree</hask>, just for simplicity.)<br />
<br />
Equipped with a <hask>Generic</hask> instance, we are ready to tell the compiler how it can serialize any representable type:<br />
<br />
<haskell><br />
putDefault :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
putDefault a = gput (from a)<br />
</haskell><br />
<br />
The type of <hask>putDefault</hask> says that we can serialize any <tt>a</tt> into a list of bits, as long as that <tt>a</tt> is <hask>Generic</hask>, and its representation <hask>Rep a</hask> has a <hask>GSerialize</hask> instance. The implementation is very simple: first convert the value to its representation using <hask>from</hask>, and then call <hask>gput</hask> on that representation.<br />
<br />
However, we still have to write a <hask>Serialize</hask> instance for the user dataype:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a) where<br />
put = putDefault<br />
</haskell><br />
<br />
=== Using GHC's new features ===<br />
<br />
What we have seen so far could all already be done, at the cost of writing a lot of boilerplate code yourself (or spending hours writing [[Template Haskell]] code to do it for you). Now we'll see how the new features of GHC can help you.<br />
<br />
==== Deriving representations ====<br />
<br />
The <hask>Generic</hask> class, and all the representation types, come with GHC in the <tt>GHC.Generics</tt> module. GHC can also derive <hask>Generic</hask> for user types, so all the user has to do is:<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveGeneric #-}<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving Generic<br />
</haskell><br />
<br />
(Standlone deriving also works fine, and you can use it for types you have not defined yourself, but are imported from somewhere else.) You will need the new <tt>DeriveGeneric</tt> language pragma.<br />
<br />
==== More general default methods ====<br />
<br />
We don't want the user to have to write the <hask>instance Serialize (UserTree a)</hask> himself, since most of the times it will just be <hask>putDefault</hask>. However, we cannot make <hask>putDefault</hask> the default implementation of the <hask>put</hask> method, because that would require adding the <hask>(Generic a, GSerialize (Rep a))</hask> constraint to the class head. This would restrict the ability to give ad-hoc instances for types that are not representable, for instance.<br />
<br />
We solved this by allowing the user to give a different signature for default methods:<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures #-}<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
</haskell><br />
<br />
With the new language pragma <tt>DefaultSignatures</tt>, GHC allows you to put the keyword <hask>default</hask> before a (new) type signature for a method inside a class declaration. If you give such a default type signature, then you have to provide a default method implementation, which will be type-checked using the default signature, and not the original one.<br />
<br />
Now the user can simply write:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
GHC fills out the implementation for <hask>put</hask> using the default method. It will type-check correctly because we have a <hask>Generic</hask> instance for <hask>UserTree</hask>, and <hask>GSerialize</hask> instances for all the representation types.<br />
<br />
=== Complete working example ===<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures, DeriveGeneric, TypeOperators, FlexibleContexts #-}<br />
<br />
import GHC.Generics<br />
import Data.Bits<br />
<br />
<br />
data Bit = O | I deriving Show<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
<br />
get :: [Bit] -> (a, [Bit])<br />
<br />
default get :: (Generic a, GSerialize (Rep a)) => [Bit] -> (a, [Bit])<br />
get xs = (to x, xs')<br />
where (x, xs') = gget xs<br />
<br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
gget :: [Bit] -> (f a, [Bit])<br />
<br />
-- | Unit: used for constructors without arguments<br />
instance GSerialize U1 where<br />
gput U1 = []<br />
gget xs = (U1, xs)<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
gget xs = (a :*: b, xs'')<br />
where (a, xs') = gget xs<br />
(b, xs'') = gget xs'<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
gget (O:xs) = (L1 x, xs')<br />
where (x, xs') = gget xs<br />
gget (I:xs) = (R1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Sums: encode choice between constructors<br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
gget xs = (M1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
gget xs = (K1 x, xs') -- LINE 54<br />
where (x, xs') = get xs<br />
<br />
instance Serialize Bool where<br />
put True = [I]<br />
put False = [O]<br />
get (I:xs) = (True, xs)<br />
get (O:xs) = (False, xs)<br />
<br />
--<br />
-- Try it out. (Normally this would be in a separate module.)<br />
--<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving (Generic, Show)<br />
<br />
instance (Serialize a) => Serialize (UserTree a)<br />
<br />
main = do<br />
let xs = put True<br />
print (fst . get $ xs :: Bool)<br />
let ys = put (Leaf :: UserTree Bool)<br />
print (fst . get $ ys :: UserTree Bool)<br />
let zs = put (Node False Leaf Leaf :: UserTree Bool)<br />
print (fst . get $ zs :: UserTree Bool)<br />
</haskell><br />
<br />
== Different perspectives ==<br />
<br />
We outline the changes introduced in 7.2 regarding support for generic programming from the perspective of three different types of users: the end-user, the generic programmer, and the GHC hacker.<br />
<br />
=== The end-user ===<br />
<br />
If you know nothing about generic programming and would like to keep it that way, then you will be pleased to know that using generics in GHC 7.2 is easier than ever. As soon as you encounter a class with a default signature (like <tt>Serialize</tt> above), you will be able to give empty instances for your datatypes, like this:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
You will need to add a <hask>deriving Generic</hask> clause to each datatype that you want to have generic implementations for. You might have datatypes that use other datatypes, and you might need <tt>Generic</tt> instances for those too. In that case, you can import the module where the datatype is defined and give a standalone deriving <tt>Generic</tt> instance. In either case, you will need the <tt>-XDeriveGeneric</tt> flag.<br />
<br />
=== The generic programmer ===<br />
<br />
If you are a library author and are eager to make your classes easy to instantiate by your users, then you should invest some time in defining instances for each of the representation types of <tt>GHC.Generics</tt> and defining a generic default method. See the example for <tt>Serialize</tt> above, and the [http://dreixel.net/research/pdf/gdmh.pdf original paper] for many other examples (but make sure to check the [[#Changes from the paper|changes from the paper]]).<br />
<br />
=== The GHC hacker ===<br />
<br />
If you are working on the GHC source code, you might find it useful to know what kind of changes were made. There is a [http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving Trac wiki page] with a lower-level overview of things and also keeping track of what still needs to be done.<br />
<br />
== Changes from the paper ==<br />
<br />
In the [http://dreixel.net/research/pdf/gdmh.pdf paper] we describe the implementation in [http://www.cs.uu.nl/wiki/UHC UHC]. The implementation in GHC is slightly different:<br />
<br />
* <tt>Representable0</tt> and <tt>Representable1</tt> have become <tt>Generic</tt> and <tt>Generic1</tt>, respectively. <tt>from0</tt>, <tt>to0</tt>, and <tt>Rep0</tt> also lost the <tt>0</tt> at the end of their names.<br />
<br />
* We are using type families, so the <tt>Generic</tt> and <tt>Generic1</tt> type classes have only one type argument. So, in GHC the classes look like what we describe in the "Avoiding extensions" part of Section 2.3 of the paper. This change affects only a generic function writer, and not a generic function user.<br />
<br />
* Default definitions (Section 3.3) work differently. In GHC we don't use a <tt>DERIVABLE</tt> pragma; instead, a type class can declare a ''generic default method'', which is akin to a standard default method, but includes a default type signature. This removes the need for a separate default definition and a pragma. For example, the <tt>Encode</tt> class of Section 3.1 is now:<br />
<haskell><br />
class Encode a where<br />
encode :: a -> [Bit]<br />
default encode :: (Generic a, Encode1 (Rep a)) => a -> [Bit]<br />
encode = encode1 . from<br />
</haskell><br />
<br />
* To derive generic functionality to a user type, the user no longer uses <hask>deriving instance</hask> (Section 4.6.1). Instead, the user gives an instance without defining the method; GHC then uses the generic default. For instance:<br />
<haskell><br />
instance Encode [a] -- works if there is an instance Generic [a]<br />
</haskell><br />
<br />
== Limitations ==<br />
<br />
We cannot derive <tt>Generic</tt> instances for:<br />
* Datatypes with a context;<br />
* Existentially-quantified datatypes;<br />
* GADTs.<br />
<br />
<br />
[[Category:GHC]]<br />
[[Category:Language extensions]]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=GHC.Generics&diff=56412GHC.Generics2013-07-17T09:25:20Z<p>Amy de B: Moved the example to a different section</p>
<hr />
<div>GHC 7.2 includes improved support for ''datatype-generic programming'' through two new features, enabled with two new flags: <tt>DeriveGeneric</tt> and <tt>DefaultSignatures</tt>. We show how this all works in this page, starting with a detailed example.<br />
<br />
Since this is a fresh new feature, it is possible that you will run into bugs when using it. If so, please<br />
[http://hackage.haskell.org/trac/ghc/wiki/ReportABug report them]!<br />
<br />
== Example: serialization ==<br />
<br />
Suppose you are writing a class for serialization of data. You have a type <hask>Bit</hask> representing bits, and a class <hask>Serialize</hask>:<br />
<br />
<haskell><br />
data Bit = O | I<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
</haskell><br />
<br />
You might have written some instances already:<br />
<br />
<haskell><br />
instance Serialize Int where<br />
put i = serializeInt i<br />
<br />
instance Serialize a => Serialize [a] where<br />
put [] = []<br />
put (h:t) = put h ++ put t<br />
</haskell><br />
<br />
A user of your library, however, will have his own datatypes, like:<br />
<br />
<haskell><br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
</haskell><br />
<br />
He will have to specify an <hask>instance Serialize (UserTree a) where ...</hask> himself. This, however, is tedious, especially because most instances will probably be rather trivial, and should be derived automatically.<br />
<br />
It is here that generic programming can help you. If you are familiar with [http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB SYB] you could use it at this stage, but now we'll see how to do this with the new features of GHC 7.2.<br />
<br />
=== Generic serialization ===<br />
<br />
First you have to tell the compiler how to serialize any datatype, in general. Since Haskell datatypes have a regular structure, this means you can just explain how to serialize a few basic datatypes.<br />
<br />
==== Representation types ====<br />
<br />
We can represent most Haskell datatypes using only the following primitive types:<br />
<br />
<haskell><br />
-- | Unit: used for constructors without arguments<br />
data U1 p = U1<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
newtype K1 i c p = K1 { unK1 :: c }<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
newtype M1 i c f p = M1 { unM1 :: f p }<br />
<br />
-- | Sums: encode choice between constructors<br />
infixr 5 :+:<br />
data (:+:) f g p = L1 (f p) | R1 (g p)<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
infixr 6 :*:<br />
data (:*:) f g p = f p :*: g p<br />
</haskell><br />
<br />
For starters, try to ignore the <tt>p</tt> parameter in all types; it's there just for future compatibility. The easiest way to understand how you can use these types to represent others is to see an example. Let's represent the <hask>UserTree</hask> type shown before:<br />
<br />
<haskell><br />
type RepUserTree a =<br />
-- A UserTree is either a Leaf, which has no arguments<br />
U1<br />
-- ... or it is a Node, which has three arguments that we put in a product<br />
:+: a :*: UserTree a :*: UserTree a<br />
</haskell><br />
<br />
Simple, right? Different constructors become alternatives of a sum, and multiple arguments become products. In fact, we want to have some more information in the representation, like datatype and constructor names, and to know if a product argument is a parameter or a type. We use the other primitives for this, and the representation looks more like:<br />
<br />
<haskell><br />
type RealRepUserTree a =<br />
-- Information about the datatype<br />
M1 D Data_UserTree (<br />
-- Leaf, with information about the constructor<br />
M1 C Con_Leaf U1<br />
-- Node, with information about the constructor<br />
:+: M1 C Con_Node (<br />
-- Constructor argument, which could have information<br />
-- about a record selector label<br />
M1 S NoSelector (<br />
-- Argument, tagged with P because it is a parameter<br />
K1 P a)<br />
-- Another argument, tagged with R because it is <br />
-- a recursive occurrence of a type<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
-- Idem<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
))<br />
</haskell><br />
<br />
A bit more complicated, but essentially the same. Datatypes like <hask>Data_UserTree</hask> are empty datatypes used only for providing meta-information in the representation; you don't have to worry much about them for now. Also, GHC generates these representations for you automatically, so you should never have to define them yourself! All of this is explained in much more detail in Section 2.1. of [http://dreixel.net/research/pdf/gdmh.pdf the original paper describing the new generic deriving mechanism].<br />
<br />
==== A generic function ====<br />
<br />
Since GHC can represent user types using only those primitive types, all you have to do is to tell GHC how to serialize each of the individual primitive types. The best way to do that is to create a new type class:<br />
<br />
<haskell><br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
</haskell><br />
<br />
This class looks very much like the original <hask>Serialize</hask> class, just that the type argument is of kind <hask>* -> *</hask>, since our generic representation types have this <tt>p</tt> parameter lying around. Now we need to give instances for each of the basic types. For units there's nothing to serialize:<br />
<br />
<haskell><br />
instance GSerialize U1 where<br />
gput U1 = []<br />
</haskell><br />
<br />
The serialization of multiple arguments is simply the concatenation of each of the individual serializations:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
</haskell><br />
<br />
The case for sums is the most interesting, as we have to record which alternative we are in. We will use a 0 for left injections and a 1 for right injections:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
</haskell><br />
<br />
We don't need to encode the meta-information, so we just go over it recursively :<br />
<br />
<haskell><br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
</haskell><br />
<br />
Finally, we're only left with the arguments. For these we will just use our first class, <hask>Serialize</hask>, again:<br />
<br />
<haskell><br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
</haskell><br />
<br />
So, if a user datatype has a parameter which is instantiated to <hask>Int</hask>, at this stage we will use the library instance for <hask>Serialize Int</hask>.<br />
<br />
==== Default implementations ====<br />
<br />
We've seen how to represent user types generically, and how to define functions on representation types. However, we still have to tie these two together, explaining how to convert user types to their representation and then applying the generic function.<br />
<br />
The representation <hask>RepUserTree</hask> we have seen earlier is only one component of the representation; we also need functions to convert to and from the user datatype into the representation. For that we use another type class:<br />
<br />
<haskell><br />
class Generic a where<br />
-- Encode the representation of a user datatype<br />
type Rep a :: * -> *<br />
-- Convert from the datatype to its representation<br />
from :: a -> (Rep a) x<br />
-- Convert from the representation to the datatype<br />
to :: (Rep a) x -> a<br />
</haskell><br />
<br />
So, for the <hask>UserTree</hask> datatype shown before, GHC generates the following instance:<br />
<br />
<haskell><br />
instance Generic (UserTree a) where<br />
type Rep (UserTree a) = RepUserTree a<br />
<br />
from Leaf = L1 U1<br />
from (Node a l r) = R1 (a :*: l :*: r)<br />
<br />
to (L1 U1) = Leaf<br />
to (R1 (a :*: l :*: r)) = Node a l r<br />
</haskell><br />
<br />
(Note that we are using the simpler representation <hask>RepUserTree</hask> instead of the real representation <hask>RealRepUserTree</hask>, just for simplicity.)<br />
<br />
Equipped with a <hask>Generic</hask> instance, we are ready to tell the compiler how it can serialize any representable type:<br />
<br />
<haskell><br />
putDefault :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
putDefault a = gput (from a)<br />
</haskell><br />
<br />
The type of <hask>putDefault</hask> says that we can serialize any <tt>a</tt> into a list of bits, as long as that <tt>a</tt> is <hask>Generic</hask>, and its representation <hask>Rep a</hask> has a <hask>GSerialize</hask> instance. The implementation is very simple: first convert the value to its representation using <hask>from</hask>, and then call <hask>gput</hask> on that representation.<br />
<br />
However, we still have to write a <hask>Serialize</hask> instance for the user dataype:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a) where<br />
put = putDefault<br />
</haskell><br />
<br />
=== Using GHC's new features ===<br />
<br />
What we have seen so far could all already be done, at the cost of writing a lot of boilerplate code yourself (or spending hours writing [[Template Haskell]] code to do it for you). Now we'll see how the new features of GHC can help you.<br />
<br />
==== Deriving representations ====<br />
<br />
The <hask>Generic</hask> class, and all the representation types, come with GHC in the <tt>GHC.Generics</tt> module. GHC can also derive <hask>Generic</hask> for user types, so all the user has to do is:<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveGeneric #-}<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving Generic<br />
</haskell><br />
<br />
(Standlone deriving also works fine, and you can use it for types you have not defined yourself, but are imported from somewhere else.) You will need the new <tt>DeriveGeneric</tt> language pragma.<br />
<br />
==== More general default methods ====<br />
<br />
We don't want the user to have to write the <hask>instance Serialize (UserTree a)</hask> himself, since most of the times it will just be <hask>putDefault</hask>. However, we cannot make <hask>putDefault</hask> the default implementation of the <hask>put</hask> method, because that would require adding the <hask>(Generic a, GSerialize (Rep a))</hask> constraint to the class head. This would restrict the ability to give ad-hoc instances for types that are not representable, for instance.<br />
<br />
We solved this by allowing the user to give a different signature for default methods:<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures #-}<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
</haskell><br />
<br />
With the new language pragma <tt>DefaultSignatures</tt>, GHC allows you to put the keyword <hask>default</hask> before a (new) type signature for a method inside a class declaration. If you give such a default type signature, then you have to provide a default method implementation, which will be type-checked using the default signature, and not the original one.<br />
<br />
Now the user can simply write:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
GHC fills out the implementation for <hask>put</hask> using the default method. It will type-check correctly because we have a <hask>Generic</hask> instance for <hask>UserTree</hask>, and <hask>GSerialize</hask> instances for all the representation types.<br />
<br />
=== Complete working example ===<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures, DeriveGeneric, TypeOperators, FlexibleContexts #-}<br />
<br />
import GHC.Generics<br />
import Data.Bits<br />
<br />
<br />
data Bit = O | I deriving Show<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
<br />
get :: [Bit] -> (a, [Bit])<br />
<br />
default get :: (Generic a, GSerialize (Rep a)) => [Bit] -> (a, [Bit])<br />
get xs = (to x, xs')<br />
where (x, xs') = gget xs<br />
<br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
gget :: [Bit] -> (f a, [Bit])<br />
<br />
-- | Unit: used for constructors without arguments<br />
instance GSerialize U1 where<br />
gput U1 = []<br />
gget xs = (U1, xs)<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
gget xs = (a :*: b, xs'')<br />
where (a, xs') = gget xs<br />
(b, xs'') = gget xs'<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
gget (O:xs) = (L1 x, xs')<br />
where (x, xs') = gget xs<br />
gget (I:xs) = (R1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Sums: encode choice between constructors<br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
gget xs = (M1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
gget xs = (K1 x, xs') -- LINE 54<br />
where (x, xs') = get xs<br />
<br />
instance Serialize Bool where<br />
put True = [I]<br />
put False = [O]<br />
get (I:xs) = (True, xs)<br />
get (O:xs) = (False, xs)<br />
<br />
--<br />
-- Try it out. (Normally this would be in a separate module.)<br />
--<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving (Generic, Show)<br />
<br />
instance (Serialize a) => Serialize (UserTree a)<br />
<br />
main = do<br />
let xs = put True<br />
print (fst . get $ xs :: Bool)<br />
let ys = put (Leaf :: UserTree Bool)<br />
print (fst . get $ ys :: UserTree Bool)<br />
let zs = put (Node False Leaf Leaf :: UserTree Bool)<br />
print (fst . get $ zs :: UserTree Bool)<br />
</haskell><br />
<br />
== Different perspectives ==<br />
<br />
We outline the changes introduced in 7.2 regarding support for generic programming from the perspective of three different types of users: the end-user, the generic programmer, and the GHC hacker.<br />
<br />
=== The end-user ===<br />
<br />
If you know nothing about generic programming and would like to keep it that way, then you will be pleased to know that using generics in GHC 7.2 is easier than ever. As soon as you encounter a class with a default signature (like <tt>Serialize</tt> above), you will be able to give empty instances for your datatypes, like this:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
You will need to add a <hask>deriving Generic</hask> clause to each datatype that you want to have generic implementations for. You might have datatypes that use other datatypes, and you might need <tt>Generic</tt> instances for those too. In that case, you can import the module where the datatype is defined and give a standalone deriving <tt>Generic</tt> instance. In either case, you will need the <tt>-XDeriveGeneric</tt> flag.<br />
<br />
=== The generic programmer ===<br />
<br />
If you are a library author and are eager to make your classes easy to instantiate by your users, then you should invest some time in defining instances for each of the representation types of <tt>GHC.Generics</tt> and defining a generic default method. See the example for <tt>Serialize</tt> above, and the [http://dreixel.net/research/pdf/gdmh.pdf original paper] for many other examples (but make sure to check the [[#Changes from the paper|changes from the paper]]).<br />
<br />
=== The GHC hacker ===<br />
<br />
If you are working on the GHC source code, you might find it useful to know what kind of changes were made. There is a [http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving Trac wiki page] with a lower-level overview of things and also keeping track of what still needs to be done.<br />
<br />
== Changes from the paper ==<br />
<br />
In the [http://dreixel.net/research/pdf/gdmh.pdf paper] we describe the implementation in [http://www.cs.uu.nl/wiki/UHC UHC]. The implementation in GHC is slightly different:<br />
<br />
* <tt>Representable0</tt> and <tt>Representable1</tt> have become <tt>Generic</tt> and <tt>Generic1</tt>, respectively. <tt>from0</tt>, <tt>to0</tt>, and <tt>Rep0</tt> also lost the <tt>0</tt> at the end of their names.<br />
<br />
* We are using type families, so the <tt>Generic</tt> and <tt>Generic1</tt> type classes have only one type argument. So, in GHC the classes look like what we describe in the "Avoiding extensions" part of Section 2.3 of the paper. This change affects only a generic function writer, and not a generic function user.<br />
<br />
* Default definitions (Section 3.3) work differently. In GHC we don't use a <tt>DERIVABLE</tt> pragma; instead, a type class can declare a ''generic default method'', which is akin to a standard default method, but includes a default type signature. This removes the need for a separate default definition and a pragma. For example, the <tt>Encode</tt> class of Section 3.1 is now:<br />
<haskell><br />
class Encode a where<br />
encode :: a -> [Bit]<br />
default encode :: (Generic a, Encode1 (Rep a)) => a -> [Bit]<br />
encode = encode1 . from<br />
</haskell><br />
<br />
* To derive generic functionality to a user type, the user no longer uses <hask>deriving instance</hask> (Section 4.6.1). Instead, the user gives an instance without defining the method; GHC then uses the generic default. For instance:<br />
<haskell><br />
instance Encode [a] -- works if there is an instance Generic [a]<br />
</haskell><br />
<br />
== Limitations ==<br />
<br />
We cannot derive <tt>Generic</tt> instances for:<br />
* Datatypes with a context;<br />
* Existentially-quantified datatypes;<br />
* GADTs.<br />
<br />
<br />
[[Category:GHC]]<br />
[[Category:Language extensions]]<br />
<br />
== Complete working example ==<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures, DeriveGeneric, TypeOperators, FlexibleContexts #-}<br />
<br />
import GHC.Generics<br />
import Data.Bits<br />
<br />
<br />
data Bit = O | I deriving Show<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
<br />
get :: [Bit] -> (a, [Bit])<br />
<br />
default get :: (Generic a, GSerialize (Rep a)) => [Bit] -> (a, [Bit])<br />
get xs = (to x, xs')<br />
where (x, xs') = gget xs<br />
<br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
gget :: [Bit] -> (f a, [Bit])<br />
<br />
-- | Unit: used for constructors without arguments<br />
instance GSerialize U1 where<br />
gput U1 = []<br />
gget xs = (U1, xs)<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
gget xs = (a :*: b, xs'')<br />
where (a, xs') = gget xs<br />
(b, xs'') = gget xs'<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
gget (O:xs) = (L1 x, xs')<br />
where (x, xs') = gget xs<br />
gget (I:xs) = (R1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Sums: encode choice between constructors<br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
gget xs = (M1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
gget xs = (K1 x, xs') -- LINE 54<br />
where (x, xs') = get xs<br />
<br />
instance Serialize Bool where<br />
put True = [I]<br />
put False = [O]<br />
get (I:xs) = (True, xs)<br />
get (O:xs) = (False, xs)<br />
<br />
--<br />
-- Try it out. (Normally this would be in a separate module.)<br />
--<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving (Generic, Show)<br />
<br />
instance (Serialize a) => Serialize (UserTree a)<br />
<br />
main = do<br />
let xs = put True<br />
print (fst . get $ xs :: Bool)<br />
let ys = put (Leaf :: UserTree Bool)<br />
print (fst . get $ ys :: UserTree Bool)<br />
let zs = put (Node False Leaf Leaf :: UserTree Bool)<br />
print (fst . get $ zs :: UserTree Bool)<br />
</haskell></div>Amy de Bhttps://wiki.haskell.org/index.php?title=GHC.Generics&diff=56411GHC.Generics2013-07-17T09:22:07Z<p>Amy de B: /* Complete Working Example */</p>
<hr />
<div>GHC 7.2 includes improved support for ''datatype-generic programming'' through two new features, enabled with two new flags: <tt>DeriveGeneric</tt> and <tt>DefaultSignatures</tt>. We show how this all works in this page, starting with a detailed example.<br />
<br />
Since this is a fresh new feature, it is possible that you will run into bugs when using it. If so, please<br />
[http://hackage.haskell.org/trac/ghc/wiki/ReportABug report them]!<br />
<br />
== Example: serialization ==<br />
<br />
Suppose you are writing a class for serialization of data. You have a type <hask>Bit</hask> representing bits, and a class <hask>Serialize</hask>:<br />
<br />
<haskell><br />
data Bit = O | I<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
</haskell><br />
<br />
You might have written some instances already:<br />
<br />
<haskell><br />
instance Serialize Int where<br />
put i = serializeInt i<br />
<br />
instance Serialize a => Serialize [a] where<br />
put [] = []<br />
put (h:t) = put h ++ put t<br />
</haskell><br />
<br />
A user of your library, however, will have his own datatypes, like:<br />
<br />
<haskell><br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
</haskell><br />
<br />
He will have to specify an <hask>instance Serialize (UserTree a) where ...</hask> himself. This, however, is tedious, especially because most instances will probably be rather trivial, and should be derived automatically.<br />
<br />
It is here that generic programming can help you. If you are familiar with [http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB SYB] you could use it at this stage, but now we'll see how to do this with the new features of GHC 7.2.<br />
<br />
=== Generic serialization ===<br />
<br />
First you have to tell the compiler how to serialize any datatype, in general. Since Haskell datatypes have a regular structure, this means you can just explain how to serialize a few basic datatypes.<br />
<br />
==== Representation types ====<br />
<br />
We can represent most Haskell datatypes using only the following primitive types:<br />
<br />
<haskell><br />
-- | Unit: used for constructors without arguments<br />
data U1 p = U1<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
newtype K1 i c p = K1 { unK1 :: c }<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
newtype M1 i c f p = M1 { unM1 :: f p }<br />
<br />
-- | Sums: encode choice between constructors<br />
infixr 5 :+:<br />
data (:+:) f g p = L1 (f p) | R1 (g p)<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
infixr 6 :*:<br />
data (:*:) f g p = f p :*: g p<br />
</haskell><br />
<br />
For starters, try to ignore the <tt>p</tt> parameter in all types; it's there just for future compatibility. The easiest way to understand how you can use these types to represent others is to see an example. Let's represent the <hask>UserTree</hask> type shown before:<br />
<br />
<haskell><br />
type RepUserTree a =<br />
-- A UserTree is either a Leaf, which has no arguments<br />
U1<br />
-- ... or it is a Node, which has three arguments that we put in a product<br />
:+: a :*: UserTree a :*: UserTree a<br />
</haskell><br />
<br />
Simple, right? Different constructors become alternatives of a sum, and multiple arguments become products. In fact, we want to have some more information in the representation, like datatype and constructor names, and to know if a product argument is a parameter or a type. We use the other primitives for this, and the representation looks more like:<br />
<br />
<haskell><br />
type RealRepUserTree a =<br />
-- Information about the datatype<br />
M1 D Data_UserTree (<br />
-- Leaf, with information about the constructor<br />
M1 C Con_Leaf U1<br />
-- Node, with information about the constructor<br />
:+: M1 C Con_Node (<br />
-- Constructor argument, which could have information<br />
-- about a record selector label<br />
M1 S NoSelector (<br />
-- Argument, tagged with P because it is a parameter<br />
K1 P a)<br />
-- Another argument, tagged with R because it is <br />
-- a recursive occurrence of a type<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
-- Idem<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
))<br />
</haskell><br />
<br />
A bit more complicated, but essentially the same. Datatypes like <hask>Data_UserTree</hask> are empty datatypes used only for providing meta-information in the representation; you don't have to worry much about them for now. Also, GHC generates these representations for you automatically, so you should never have to define them yourself! All of this is explained in much more detail in Section 2.1. of [http://dreixel.net/research/pdf/gdmh.pdf the original paper describing the new generic deriving mechanism].<br />
<br />
==== A generic function ====<br />
<br />
Since GHC can represent user types using only those primitive types, all you have to do is to tell GHC how to serialize each of the individual primitive types. The best way to do that is to create a new type class:<br />
<br />
<haskell><br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
</haskell><br />
<br />
This class looks very much like the original <hask>Serialize</hask> class, just that the type argument is of kind <hask>* -> *</hask>, since our generic representation types have this <tt>p</tt> parameter lying around. Now we need to give instances for each of the basic types. For units there's nothing to serialize:<br />
<br />
<haskell><br />
instance GSerialize U1 where<br />
gput U1 = []<br />
</haskell><br />
<br />
The serialization of multiple arguments is simply the concatenation of each of the individual serializations:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
</haskell><br />
<br />
The case for sums is the most interesting, as we have to record which alternative we are in. We will use a 0 for left injections and a 1 for right injections:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
</haskell><br />
<br />
We don't need to encode the meta-information, so we just go over it recursively :<br />
<br />
<haskell><br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
</haskell><br />
<br />
Finally, we're only left with the arguments. For these we will just use our first class, <hask>Serialize</hask>, again:<br />
<br />
<haskell><br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
</haskell><br />
<br />
So, if a user datatype has a parameter which is instantiated to <hask>Int</hask>, at this stage we will use the library instance for <hask>Serialize Int</hask>.<br />
<br />
==== Default implementations ====<br />
<br />
We've seen how to represent user types generically, and how to define functions on representation types. However, we still have to tie these two together, explaining how to convert user types to their representation and then applying the generic function.<br />
<br />
The representation <hask>RepUserTree</hask> we have seen earlier is only one component of the representation; we also need functions to convert to and from the user datatype into the representation. For that we use another type class:<br />
<br />
<haskell><br />
class Generic a where<br />
-- Encode the representation of a user datatype<br />
type Rep a :: * -> *<br />
-- Convert from the datatype to its representation<br />
from :: a -> (Rep a) x<br />
-- Convert from the representation to the datatype<br />
to :: (Rep a) x -> a<br />
</haskell><br />
<br />
So, for the <hask>UserTree</hask> datatype shown before, GHC generates the following instance:<br />
<br />
<haskell><br />
instance Generic (UserTree a) where<br />
type Rep (UserTree a) = RepUserTree a<br />
<br />
from Leaf = L1 U1<br />
from (Node a l r) = R1 (a :*: l :*: r)<br />
<br />
to (L1 U1) = Leaf<br />
to (R1 (a :*: l :*: r)) = Node a l r<br />
</haskell><br />
<br />
(Note that we are using the simpler representation <hask>RepUserTree</hask> instead of the real representation <hask>RealRepUserTree</hask>, just for simplicity.)<br />
<br />
Equipped with a <hask>Generic</hask> instance, we are ready to tell the compiler how it can serialize any representable type:<br />
<br />
<haskell><br />
putDefault :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
putDefault a = gput (from a)<br />
</haskell><br />
<br />
The type of <hask>putDefault</hask> says that we can serialize any <tt>a</tt> into a list of bits, as long as that <tt>a</tt> is <hask>Generic</hask>, and its representation <hask>Rep a</hask> has a <hask>GSerialize</hask> instance. The implementation is very simple: first convert the value to its representation using <hask>from</hask>, and then call <hask>gput</hask> on that representation.<br />
<br />
However, we still have to write a <hask>Serialize</hask> instance for the user dataype:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a) where<br />
put = putDefault<br />
</haskell><br />
<br />
=== Using GHC's new features ===<br />
<br />
What we have seen so far could all already be done, at the cost of writing a lot of boilerplate code yourself (or spending hours writing [[Template Haskell]] code to do it for you). Now we'll see how the new features of GHC can help you.<br />
<br />
==== Deriving representations ====<br />
<br />
The <hask>Generic</hask> class, and all the representation types, come with GHC in the <tt>GHC.Generics</tt> module. GHC can also derive <hask>Generic</hask> for user types, so all the user has to do is:<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveGeneric #-}<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving Generic<br />
</haskell><br />
<br />
(Standlone deriving also works fine, and you can use it for types you have not defined yourself, but are imported from somewhere else.) You will need the new <tt>DeriveGeneric</tt> language pragma.<br />
<br />
==== More general default methods ====<br />
<br />
We don't want the user to have to write the <hask>instance Serialize (UserTree a)</hask> himself, since most of the times it will just be <hask>putDefault</hask>. However, we cannot make <hask>putDefault</hask> the default implementation of the <hask>put</hask> method, because that would require adding the <hask>(Generic a, GSerialize (Rep a))</hask> constraint to the class head. This would restrict the ability to give ad-hoc instances for types that are not representable, for instance.<br />
<br />
We solved this by allowing the user to give a different signature for default methods:<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures #-}<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
</haskell><br />
<br />
With the new language pragma <tt>DefaultSignatures</tt>, GHC allows you to put the keyword <hask>default</hask> before a (new) type signature for a method inside a class declaration. If you give such a default type signature, then you have to provide a default method implementation, which will be type-checked using the default signature, and not the original one.<br />
<br />
Now the user can simply write:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
GHC fills out the implementation for <hask>put</hask> using the default method. It will type-check correctly because we have a <hask>Generic</hask> instance for <hask>UserTree</hask>, and <hask>GSerialize</hask> instances for all the representation types.<br />
<br />
== Different perspectives ==<br />
<br />
We outline the changes introduced in 7.2 regarding support for generic programming from the perspective of three different types of users: the end-user, the generic programmer, and the GHC hacker.<br />
<br />
=== The end-user ===<br />
<br />
If you know nothing about generic programming and would like to keep it that way, then you will be pleased to know that using generics in GHC 7.2 is easier than ever. As soon as you encounter a class with a default signature (like <tt>Serialize</tt> above), you will be able to give empty instances for your datatypes, like this:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
You will need to add a <hask>deriving Generic</hask> clause to each datatype that you want to have generic implementations for. You might have datatypes that use other datatypes, and you might need <tt>Generic</tt> instances for those too. In that case, you can import the module where the datatype is defined and give a standalone deriving <tt>Generic</tt> instance. In either case, you will need the <tt>-XDeriveGeneric</tt> flag.<br />
<br />
=== The generic programmer ===<br />
<br />
If you are a library author and are eager to make your classes easy to instantiate by your users, then you should invest some time in defining instances for each of the representation types of <tt>GHC.Generics</tt> and defining a generic default method. See the example for <tt>Serialize</tt> above, and the [http://dreixel.net/research/pdf/gdmh.pdf original paper] for many other examples (but make sure to check the [[#Changes from the paper|changes from the paper]]).<br />
<br />
=== The GHC hacker ===<br />
<br />
If you are working on the GHC source code, you might find it useful to know what kind of changes were made. There is a [http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving Trac wiki page] with a lower-level overview of things and also keeping track of what still needs to be done.<br />
<br />
== Changes from the paper ==<br />
<br />
In the [http://dreixel.net/research/pdf/gdmh.pdf paper] we describe the implementation in [http://www.cs.uu.nl/wiki/UHC UHC]. The implementation in GHC is slightly different:<br />
<br />
* <tt>Representable0</tt> and <tt>Representable1</tt> have become <tt>Generic</tt> and <tt>Generic1</tt>, respectively. <tt>from0</tt>, <tt>to0</tt>, and <tt>Rep0</tt> also lost the <tt>0</tt> at the end of their names.<br />
<br />
* We are using type families, so the <tt>Generic</tt> and <tt>Generic1</tt> type classes have only one type argument. So, in GHC the classes look like what we describe in the "Avoiding extensions" part of Section 2.3 of the paper. This change affects only a generic function writer, and not a generic function user.<br />
<br />
* Default definitions (Section 3.3) work differently. In GHC we don't use a <tt>DERIVABLE</tt> pragma; instead, a type class can declare a ''generic default method'', which is akin to a standard default method, but includes a default type signature. This removes the need for a separate default definition and a pragma. For example, the <tt>Encode</tt> class of Section 3.1 is now:<br />
<haskell><br />
class Encode a where<br />
encode :: a -> [Bit]<br />
default encode :: (Generic a, Encode1 (Rep a)) => a -> [Bit]<br />
encode = encode1 . from<br />
</haskell><br />
<br />
* To derive generic functionality to a user type, the user no longer uses <hask>deriving instance</hask> (Section 4.6.1). Instead, the user gives an instance without defining the method; GHC then uses the generic default. For instance:<br />
<haskell><br />
instance Encode [a] -- works if there is an instance Generic [a]<br />
</haskell><br />
<br />
== Limitations ==<br />
<br />
We cannot derive <tt>Generic</tt> instances for:<br />
* Datatypes with a context;<br />
* Existentially-quantified datatypes;<br />
* GADTs.<br />
<br />
<br />
[[Category:GHC]]<br />
[[Category:Language extensions]]<br />
<br />
== Complete working example ==<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures, DeriveGeneric, TypeOperators, FlexibleContexts #-}<br />
<br />
import GHC.Generics<br />
import Data.Bits<br />
<br />
<br />
data Bit = O | I deriving Show<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
<br />
get :: [Bit] -> (a, [Bit])<br />
<br />
default get :: (Generic a, GSerialize (Rep a)) => [Bit] -> (a, [Bit])<br />
get xs = (to x, xs')<br />
where (x, xs') = gget xs<br />
<br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
gget :: [Bit] -> (f a, [Bit])<br />
<br />
-- | Unit: used for constructors without arguments<br />
instance GSerialize U1 where<br />
gput U1 = []<br />
gget xs = (U1, xs)<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
gget xs = (a :*: b, xs'')<br />
where (a, xs') = gget xs<br />
(b, xs'') = gget xs'<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
gget (O:xs) = (L1 x, xs')<br />
where (x, xs') = gget xs<br />
gget (I:xs) = (R1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Sums: encode choice between constructors<br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
gget xs = (M1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
gget xs = (K1 x, xs') -- LINE 54<br />
where (x, xs') = get xs<br />
<br />
instance Serialize Bool where<br />
put True = [I]<br />
put False = [O]<br />
get (I:xs) = (True, xs)<br />
get (O:xs) = (False, xs)<br />
<br />
--<br />
-- Try it out. (Normally this would be in a separate module.)<br />
--<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving (Generic, Show)<br />
<br />
instance (Serialize a) => Serialize (UserTree a)<br />
<br />
main = do<br />
let xs = put True<br />
print (fst . get $ xs :: Bool)<br />
let ys = put (Leaf :: UserTree Bool)<br />
print (fst . get $ ys :: UserTree Bool)<br />
let zs = put (Node False Leaf Leaf :: UserTree Bool)<br />
print (fst . get $ zs :: UserTree Bool)<br />
</haskell></div>Amy de Bhttps://wiki.haskell.org/index.php?title=GHC.Generics&diff=56410GHC.Generics2013-07-17T09:21:40Z<p>Amy de B: Added complete working example</p>
<hr />
<div>GHC 7.2 includes improved support for ''datatype-generic programming'' through two new features, enabled with two new flags: <tt>DeriveGeneric</tt> and <tt>DefaultSignatures</tt>. We show how this all works in this page, starting with a detailed example.<br />
<br />
Since this is a fresh new feature, it is possible that you will run into bugs when using it. If so, please<br />
[http://hackage.haskell.org/trac/ghc/wiki/ReportABug report them]!<br />
<br />
== Example: serialization ==<br />
<br />
Suppose you are writing a class for serialization of data. You have a type <hask>Bit</hask> representing bits, and a class <hask>Serialize</hask>:<br />
<br />
<haskell><br />
data Bit = O | I<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
</haskell><br />
<br />
You might have written some instances already:<br />
<br />
<haskell><br />
instance Serialize Int where<br />
put i = serializeInt i<br />
<br />
instance Serialize a => Serialize [a] where<br />
put [] = []<br />
put (h:t) = put h ++ put t<br />
</haskell><br />
<br />
A user of your library, however, will have his own datatypes, like:<br />
<br />
<haskell><br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
</haskell><br />
<br />
He will have to specify an <hask>instance Serialize (UserTree a) where ...</hask> himself. This, however, is tedious, especially because most instances will probably be rather trivial, and should be derived automatically.<br />
<br />
It is here that generic programming can help you. If you are familiar with [http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB SYB] you could use it at this stage, but now we'll see how to do this with the new features of GHC 7.2.<br />
<br />
=== Generic serialization ===<br />
<br />
First you have to tell the compiler how to serialize any datatype, in general. Since Haskell datatypes have a regular structure, this means you can just explain how to serialize a few basic datatypes.<br />
<br />
==== Representation types ====<br />
<br />
We can represent most Haskell datatypes using only the following primitive types:<br />
<br />
<haskell><br />
-- | Unit: used for constructors without arguments<br />
data U1 p = U1<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
newtype K1 i c p = K1 { unK1 :: c }<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
newtype M1 i c f p = M1 { unM1 :: f p }<br />
<br />
-- | Sums: encode choice between constructors<br />
infixr 5 :+:<br />
data (:+:) f g p = L1 (f p) | R1 (g p)<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
infixr 6 :*:<br />
data (:*:) f g p = f p :*: g p<br />
</haskell><br />
<br />
For starters, try to ignore the <tt>p</tt> parameter in all types; it's there just for future compatibility. The easiest way to understand how you can use these types to represent others is to see an example. Let's represent the <hask>UserTree</hask> type shown before:<br />
<br />
<haskell><br />
type RepUserTree a =<br />
-- A UserTree is either a Leaf, which has no arguments<br />
U1<br />
-- ... or it is a Node, which has three arguments that we put in a product<br />
:+: a :*: UserTree a :*: UserTree a<br />
</haskell><br />
<br />
Simple, right? Different constructors become alternatives of a sum, and multiple arguments become products. In fact, we want to have some more information in the representation, like datatype and constructor names, and to know if a product argument is a parameter or a type. We use the other primitives for this, and the representation looks more like:<br />
<br />
<haskell><br />
type RealRepUserTree a =<br />
-- Information about the datatype<br />
M1 D Data_UserTree (<br />
-- Leaf, with information about the constructor<br />
M1 C Con_Leaf U1<br />
-- Node, with information about the constructor<br />
:+: M1 C Con_Node (<br />
-- Constructor argument, which could have information<br />
-- about a record selector label<br />
M1 S NoSelector (<br />
-- Argument, tagged with P because it is a parameter<br />
K1 P a)<br />
-- Another argument, tagged with R because it is <br />
-- a recursive occurrence of a type<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
-- Idem<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
))<br />
</haskell><br />
<br />
A bit more complicated, but essentially the same. Datatypes like <hask>Data_UserTree</hask> are empty datatypes used only for providing meta-information in the representation; you don't have to worry much about them for now. Also, GHC generates these representations for you automatically, so you should never have to define them yourself! All of this is explained in much more detail in Section 2.1. of [http://dreixel.net/research/pdf/gdmh.pdf the original paper describing the new generic deriving mechanism].<br />
<br />
==== A generic function ====<br />
<br />
Since GHC can represent user types using only those primitive types, all you have to do is to tell GHC how to serialize each of the individual primitive types. The best way to do that is to create a new type class:<br />
<br />
<haskell><br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
</haskell><br />
<br />
This class looks very much like the original <hask>Serialize</hask> class, just that the type argument is of kind <hask>* -> *</hask>, since our generic representation types have this <tt>p</tt> parameter lying around. Now we need to give instances for each of the basic types. For units there's nothing to serialize:<br />
<br />
<haskell><br />
instance GSerialize U1 where<br />
gput U1 = []<br />
</haskell><br />
<br />
The serialization of multiple arguments is simply the concatenation of each of the individual serializations:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
</haskell><br />
<br />
The case for sums is the most interesting, as we have to record which alternative we are in. We will use a 0 for left injections and a 1 for right injections:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
</haskell><br />
<br />
We don't need to encode the meta-information, so we just go over it recursively :<br />
<br />
<haskell><br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
</haskell><br />
<br />
Finally, we're only left with the arguments. For these we will just use our first class, <hask>Serialize</hask>, again:<br />
<br />
<haskell><br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
</haskell><br />
<br />
So, if a user datatype has a parameter which is instantiated to <hask>Int</hask>, at this stage we will use the library instance for <hask>Serialize Int</hask>.<br />
<br />
==== Default implementations ====<br />
<br />
We've seen how to represent user types generically, and how to define functions on representation types. However, we still have to tie these two together, explaining how to convert user types to their representation and then applying the generic function.<br />
<br />
The representation <hask>RepUserTree</hask> we have seen earlier is only one component of the representation; we also need functions to convert to and from the user datatype into the representation. For that we use another type class:<br />
<br />
<haskell><br />
class Generic a where<br />
-- Encode the representation of a user datatype<br />
type Rep a :: * -> *<br />
-- Convert from the datatype to its representation<br />
from :: a -> (Rep a) x<br />
-- Convert from the representation to the datatype<br />
to :: (Rep a) x -> a<br />
</haskell><br />
<br />
So, for the <hask>UserTree</hask> datatype shown before, GHC generates the following instance:<br />
<br />
<haskell><br />
instance Generic (UserTree a) where<br />
type Rep (UserTree a) = RepUserTree a<br />
<br />
from Leaf = L1 U1<br />
from (Node a l r) = R1 (a :*: l :*: r)<br />
<br />
to (L1 U1) = Leaf<br />
to (R1 (a :*: l :*: r)) = Node a l r<br />
</haskell><br />
<br />
(Note that we are using the simpler representation <hask>RepUserTree</hask> instead of the real representation <hask>RealRepUserTree</hask>, just for simplicity.)<br />
<br />
Equipped with a <hask>Generic</hask> instance, we are ready to tell the compiler how it can serialize any representable type:<br />
<br />
<haskell><br />
putDefault :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
putDefault a = gput (from a)<br />
</haskell><br />
<br />
The type of <hask>putDefault</hask> says that we can serialize any <tt>a</tt> into a list of bits, as long as that <tt>a</tt> is <hask>Generic</hask>, and its representation <hask>Rep a</hask> has a <hask>GSerialize</hask> instance. The implementation is very simple: first convert the value to its representation using <hask>from</hask>, and then call <hask>gput</hask> on that representation.<br />
<br />
However, we still have to write a <hask>Serialize</hask> instance for the user dataype:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a) where<br />
put = putDefault<br />
</haskell><br />
<br />
=== Using GHC's new features ===<br />
<br />
What we have seen so far could all already be done, at the cost of writing a lot of boilerplate code yourself (or spending hours writing [[Template Haskell]] code to do it for you). Now we'll see how the new features of GHC can help you.<br />
<br />
==== Deriving representations ====<br />
<br />
The <hask>Generic</hask> class, and all the representation types, come with GHC in the <tt>GHC.Generics</tt> module. GHC can also derive <hask>Generic</hask> for user types, so all the user has to do is:<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveGeneric #-}<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving Generic<br />
</haskell><br />
<br />
(Standlone deriving also works fine, and you can use it for types you have not defined yourself, but are imported from somewhere else.) You will need the new <tt>DeriveGeneric</tt> language pragma.<br />
<br />
==== More general default methods ====<br />
<br />
We don't want the user to have to write the <hask>instance Serialize (UserTree a)</hask> himself, since most of the times it will just be <hask>putDefault</hask>. However, we cannot make <hask>putDefault</hask> the default implementation of the <hask>put</hask> method, because that would require adding the <hask>(Generic a, GSerialize (Rep a))</hask> constraint to the class head. This would restrict the ability to give ad-hoc instances for types that are not representable, for instance.<br />
<br />
We solved this by allowing the user to give a different signature for default methods:<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures #-}<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
</haskell><br />
<br />
With the new language pragma <tt>DefaultSignatures</tt>, GHC allows you to put the keyword <hask>default</hask> before a (new) type signature for a method inside a class declaration. If you give such a default type signature, then you have to provide a default method implementation, which will be type-checked using the default signature, and not the original one.<br />
<br />
Now the user can simply write:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
GHC fills out the implementation for <hask>put</hask> using the default method. It will type-check correctly because we have a <hask>Generic</hask> instance for <hask>UserTree</hask>, and <hask>GSerialize</hask> instances for all the representation types.<br />
<br />
== Different perspectives ==<br />
<br />
We outline the changes introduced in 7.2 regarding support for generic programming from the perspective of three different types of users: the end-user, the generic programmer, and the GHC hacker.<br />
<br />
=== The end-user ===<br />
<br />
If you know nothing about generic programming and would like to keep it that way, then you will be pleased to know that using generics in GHC 7.2 is easier than ever. As soon as you encounter a class with a default signature (like <tt>Serialize</tt> above), you will be able to give empty instances for your datatypes, like this:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
You will need to add a <hask>deriving Generic</hask> clause to each datatype that you want to have generic implementations for. You might have datatypes that use other datatypes, and you might need <tt>Generic</tt> instances for those too. In that case, you can import the module where the datatype is defined and give a standalone deriving <tt>Generic</tt> instance. In either case, you will need the <tt>-XDeriveGeneric</tt> flag.<br />
<br />
=== The generic programmer ===<br />
<br />
If you are a library author and are eager to make your classes easy to instantiate by your users, then you should invest some time in defining instances for each of the representation types of <tt>GHC.Generics</tt> and defining a generic default method. See the example for <tt>Serialize</tt> above, and the [http://dreixel.net/research/pdf/gdmh.pdf original paper] for many other examples (but make sure to check the [[#Changes from the paper|changes from the paper]]).<br />
<br />
=== The GHC hacker ===<br />
<br />
If you are working on the GHC source code, you might find it useful to know what kind of changes were made. There is a [http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving Trac wiki page] with a lower-level overview of things and also keeping track of what still needs to be done.<br />
<br />
== Changes from the paper ==<br />
<br />
In the [http://dreixel.net/research/pdf/gdmh.pdf paper] we describe the implementation in [http://www.cs.uu.nl/wiki/UHC UHC]. The implementation in GHC is slightly different:<br />
<br />
* <tt>Representable0</tt> and <tt>Representable1</tt> have become <tt>Generic</tt> and <tt>Generic1</tt>, respectively. <tt>from0</tt>, <tt>to0</tt>, and <tt>Rep0</tt> also lost the <tt>0</tt> at the end of their names.<br />
<br />
* We are using type families, so the <tt>Generic</tt> and <tt>Generic1</tt> type classes have only one type argument. So, in GHC the classes look like what we describe in the "Avoiding extensions" part of Section 2.3 of the paper. This change affects only a generic function writer, and not a generic function user.<br />
<br />
* Default definitions (Section 3.3) work differently. In GHC we don't use a <tt>DERIVABLE</tt> pragma; instead, a type class can declare a ''generic default method'', which is akin to a standard default method, but includes a default type signature. This removes the need for a separate default definition and a pragma. For example, the <tt>Encode</tt> class of Section 3.1 is now:<br />
<haskell><br />
class Encode a where<br />
encode :: a -> [Bit]<br />
default encode :: (Generic a, Encode1 (Rep a)) => a -> [Bit]<br />
encode = encode1 . from<br />
</haskell><br />
<br />
* To derive generic functionality to a user type, the user no longer uses <hask>deriving instance</hask> (Section 4.6.1). Instead, the user gives an instance without defining the method; GHC then uses the generic default. For instance:<br />
<haskell><br />
instance Encode [a] -- works if there is an instance Generic [a]<br />
</haskell><br />
<br />
== Limitations ==<br />
<br />
We cannot derive <tt>Generic</tt> instances for:<br />
* Datatypes with a context;<br />
* Existentially-quantified datatypes;<br />
* GADTs.<br />
<br />
<br />
[[Category:GHC]]<br />
[[Category:Language extensions]]<br />
<br />
== Complete Working Example ==<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures, DeriveGeneric, TypeOperators, FlexibleContexts #-}<br />
<br />
import GHC.Generics<br />
import Data.Bits<br />
<br />
<br />
data Bit = O | I deriving Show<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
<br />
get :: [Bit] -> (a, [Bit])<br />
<br />
default get :: (Generic a, GSerialize (Rep a)) => [Bit] -> (a, [Bit])<br />
get xs = (to x, xs')<br />
where (x, xs') = gget xs<br />
<br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
gget :: [Bit] -> (f a, [Bit])<br />
<br />
-- | Unit: used for constructors without arguments<br />
instance GSerialize U1 where<br />
gput U1 = []<br />
gget xs = (U1, xs)<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
gget xs = (a :*: b, xs'')<br />
where (a, xs') = gget xs<br />
(b, xs'') = gget xs'<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
gget (O:xs) = (L1 x, xs')<br />
where (x, xs') = gget xs<br />
gget (I:xs) = (R1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Sums: encode choice between constructors<br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
gget xs = (M1 x, xs')<br />
where (x, xs') = gget xs<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
gget xs = (K1 x, xs') -- LINE 54<br />
where (x, xs') = get xs<br />
<br />
instance Serialize Bool where<br />
put True = [I]<br />
put False = [O]<br />
get (I:xs) = (True, xs)<br />
get (O:xs) = (False, xs)<br />
<br />
--<br />
-- Try it out. (Normally this would be in a separate module.)<br />
--<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving (Generic, Show)<br />
<br />
instance (Serialize a) => Serialize (UserTree a)<br />
<br />
main = do<br />
let xs = put True<br />
print (fst . get $ xs :: Bool)<br />
let ys = put (Leaf :: UserTree Bool)<br />
print (fst . get $ ys :: UserTree Bool)<br />
let zs = put (Node False Leaf Leaf :: UserTree Bool)<br />
print (fst . get $ zs :: UserTree Bool)<br />
</haskell></div>Amy de Bhttps://wiki.haskell.org/index.php?title=GHC.Generics&diff=56390GHC.Generics2013-07-11T10:10:39Z<p>Amy de B: Fixed a typo in the code</p>
<hr />
<div>GHC 7.2 includes improved support for ''datatype-generic programming'' through two new features, enabled with two new flags: <tt>DeriveGeneric</tt> and <tt>DefaultSignatures</tt>. We show how this all works in this page, starting with a detailed example.<br />
<br />
Since this is a fresh new feature, it is possible that you will run into bugs when using it. If so, please<br />
[http://hackage.haskell.org/trac/ghc/wiki/ReportABug report them]!<br />
<br />
== Example: serialization ==<br />
<br />
Suppose you are writing a class for serialization of data. You have a type <hask>Bit</hask> representing bits, and a class <hask>Serialize</hask>:<br />
<br />
<haskell><br />
data Bit = O | I<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
</haskell><br />
<br />
You might have written some instances already:<br />
<br />
<haskell><br />
instance Serialize Int where<br />
put i = serializeInt i<br />
<br />
instance Serialize a => Serialize [a] where<br />
put [] = []<br />
put (h:t) = put h ++ put t<br />
</haskell><br />
<br />
A user of your library, however, will have his own datatypes, like:<br />
<br />
<haskell><br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
</haskell><br />
<br />
He will have to specify an <hask>instance Serialize (UserTree a) where ...</hask> himself. This, however, is tedious, especially because most instances will probably be rather trivial, and should be derived automatically.<br />
<br />
It is here that generic programming can help you. If you are familiar with [http://www.cs.uu.nl/wiki/bin/view/GenericProgramming/SYB SYB] you could use it at this stage, but now we'll see how to do this with the new features of GHC 7.2.<br />
<br />
=== Generic serialization ===<br />
<br />
First you have to tell the compiler how to serialize any datatype, in general. Since Haskell datatypes have a regular structure, this means you can just explain how to serialize a few basic datatypes.<br />
<br />
==== Representation types ====<br />
<br />
We can represent most Haskell datatypes using only the following primitive types:<br />
<br />
<haskell><br />
-- | Unit: used for constructors without arguments<br />
data U1 p = U1<br />
<br />
-- | Constants, additional parameters and recursion of kind *<br />
newtype K1 i c p = K1 { unK1 :: c }<br />
<br />
-- | Meta-information (constructor names, etc.)<br />
newtype M1 i c f p = M1 { unM1 :: f p }<br />
<br />
-- | Sums: encode choice between constructors<br />
infixr 5 :+:<br />
data (:+:) f g p = L1 (f p) | R1 (g p)<br />
<br />
-- | Products: encode multiple arguments to constructors<br />
infixr 6 :*:<br />
data (:*:) f g p = f p :*: g p<br />
</haskell><br />
<br />
For starters, try to ignore the <tt>p</tt> parameter in all types; it's there just for future compatibility. The easiest way to understand how you can use these types to represent others is to see an example. Let's represent the <hask>UserTree</hask> type shown before:<br />
<br />
<haskell><br />
type RepUserTree a =<br />
-- A UserTree is either a Leaf, which has no arguments<br />
U1<br />
-- ... or it is a Node, which has three arguments that we put in a product<br />
:+: a :*: UserTree a :*: UserTree a<br />
</haskell><br />
<br />
Simple, right? Different constructors become alternatives of a sum, and multiple arguments become products. In fact, we want to have some more information in the representation, like datatype and constructor names, and to know if a product argument is a parameter or a type. We use the other primitives for this, and the representation looks more like:<br />
<br />
<haskell><br />
type RealRepUserTree a =<br />
-- Information about the datatype<br />
M1 D Data_UserTree (<br />
-- Leaf, with information about the constructor<br />
M1 C Con_Leaf U1<br />
-- Node, with information about the constructor<br />
:+: M1 C Con_Node (<br />
-- Constructor argument, which could have information<br />
-- about a record selector label<br />
M1 S NoSelector (<br />
-- Argument, tagged with P because it is a parameter<br />
K1 P a)<br />
-- Another argument, tagged with R because it is <br />
-- a recursive occurrence of a type<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
-- Idem<br />
:*: M1 S NoSelector (K1 R (UserTree a))<br />
))<br />
</haskell><br />
<br />
A bit more complicated, but essentially the same. Datatypes like <hask>Data_UserTree</hask> are empty datatypes used only for providing meta-information in the representation; you don't have to worry much about them for now. Also, GHC generates these representations for you automatically, so you should never have to define them yourself! All of this is explained in much more detail in Section 2.1. of [http://dreixel.net/research/pdf/gdmh.pdf the original paper describing the new generic deriving mechanism].<br />
<br />
==== A generic function ====<br />
<br />
Since GHC can represent user types using only those primitive types, all you have to do is to tell GHC how to serialize each of the individual primitive types. The best way to do that is to create a new type class:<br />
<br />
<haskell><br />
class GSerialize f where<br />
gput :: f a -> [Bit]<br />
</haskell><br />
<br />
This class looks very much like the original <hask>Serialize</hask> class, just that the type argument is of kind <hask>* -> *</hask>, since our generic representation types have this <tt>p</tt> parameter lying around. Now we need to give instances for each of the basic types. For units there's nothing to serialize:<br />
<br />
<haskell><br />
instance GSerialize U1 where<br />
gput U1 = []<br />
</haskell><br />
<br />
The serialization of multiple arguments is simply the concatenation of each of the individual serializations:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where<br />
gput (a :*: b) = gput a ++ gput b<br />
</haskell><br />
<br />
The case for sums is the most interesting, as we have to record which alternative we are in. We will use a 0 for left injections and a 1 for right injections:<br />
<br />
<haskell><br />
instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where<br />
gput (L1 x) = O : gput x<br />
gput (R1 x) = I : gput x<br />
</haskell><br />
<br />
We don't need to encode the meta-information, so we just go over it recursively :<br />
<br />
<haskell><br />
instance (GSerialize a) => GSerialize (M1 i c a) where<br />
gput (M1 x) = gput x<br />
</haskell><br />
<br />
Finally, we're only left with the arguments. For these we will just use our first class, <hask>Serialize</hask>, again:<br />
<br />
<haskell><br />
instance (Serialize a) => GSerialize (K1 i a) where<br />
gput (K1 x) = put x<br />
</haskell><br />
<br />
So, if a user datatype has a parameter which is instantiated to <hask>Int</hask>, at this stage we will use the library instance for <hask>Serialize Int</hask>.<br />
<br />
==== Default implementations ====<br />
<br />
We've seen how to represent user types generically, and how to define functions on representation types. However, we still have to tie these two together, explaining how to convert user types to their representation and then applying the generic function.<br />
<br />
The representation <hask>RepUserTree</hask> we have seen earlier is only one component of the representation; we also need functions to convert to and from the user datatype into the representation. For that we use another type class:<br />
<br />
<haskell><br />
class Generic a where<br />
-- Encode the representation of a user datatype<br />
type Rep a :: * -> *<br />
-- Convert from the datatype to its representation<br />
from :: a -> (Rep a) x<br />
-- Convert from the representation to the datatype<br />
to :: (Rep a) x -> a<br />
</haskell><br />
<br />
So, for the <hask>UserTree</hask> datatype shown before, GHC generates the following instance:<br />
<br />
<haskell><br />
instance Generic (UserTree a) where<br />
type Rep (UserTree a) = RepUserTree a<br />
<br />
from Leaf = L1 U1<br />
from (Node a l r) = R1 (a :*: l :*: r)<br />
<br />
to (L1 U1) = Leaf<br />
to (R1 (a :*: l :*: r)) = Node a l r<br />
</haskell><br />
<br />
(Note that we are using the simpler representation <hask>RepUserTree</hask> instead of the real representation <hask>RealRepUserTree</hask>, just for simplicity.)<br />
<br />
Equipped with a <hask>Generic</hask> instance, we are ready to tell the compiler how it can serialize any representable type:<br />
<br />
<haskell><br />
putDefault :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
putDefault a = gput (from a)<br />
</haskell><br />
<br />
The type of <hask>putDefault</hask> says that we can serialize any <tt>a</tt> into a list of bits, as long as that <tt>a</tt> is <hask>Generic</hask>, and its representation <hask>Rep a</hask> has a <hask>GSerialize</hask> instance. The implementation is very simple: first convert the value to its representation using <hask>from</hask>, and then call <hask>gput</hask> on that representation.<br />
<br />
However, we still have to write a <hask>Serialize</hask> instance for the user dataype:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a) where<br />
put = putDefault<br />
</haskell><br />
<br />
=== Using GHC's new features ===<br />
<br />
What we have seen so far could all already be done, at the cost of writing a lot of boilerplate code yourself (or spending hours writing [[Template Haskell]] code to do it for you). Now we'll see how the new features of GHC can help you.<br />
<br />
==== Deriving representations ====<br />
<br />
The <hask>Generic</hask> class, and all the representation types, come with GHC in the <tt>GHC.Generics</tt> module. GHC can also derive <hask>Generic</hask> for user types, so all the user has to do is:<br />
<br />
<haskell><br />
{-# LANGUAGE DeriveGeneric #-}<br />
<br />
data UserTree a = Node a (UserTree a) (UserTree a) | Leaf<br />
deriving Generic<br />
</haskell><br />
<br />
(Standlone deriving also works fine, and you can use it for types you have not defined yourself, but are imported from somewhere else.) You will need the new <tt>DeriveGeneric</tt> language pragma.<br />
<br />
==== More general default methods ====<br />
<br />
We don't want the user to have to write the <hask>instance Serialize (UserTree a)</hask> himself, since most of the times it will just be <hask>putDefault</hask>. However, we cannot make <hask>putDefault</hask> the default implementation of the <hask>put</hask> method, because that would require adding the <hask>(Generic a, GSerialize (Rep a))</hask> constraint to the class head. This would restrict the ability to give ad-hoc instances for types that are not representable, for instance.<br />
<br />
We solved this by allowing the user to give a different signature for default methods:<br />
<br />
<haskell><br />
{-# LANGUAGE DefaultSignatures #-}<br />
<br />
class Serialize a where<br />
put :: a -> [Bit]<br />
<br />
default put :: (Generic a, GSerialize (Rep a)) => a -> [Bit]<br />
put a = gput (from a)<br />
</haskell><br />
<br />
With the new language pragma <tt>DefaultSignatures</tt>, GHC allows you to put the keyword <hask>default</hask> before a (new) type signature for a method inside a class declaration. If you give such a default type signature, then you have to provide a default method implementation, which will be type-checked using the default signature, and not the original one.<br />
<br />
Now the user can simply write:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
GHC fills out the implementation for <hask>put</hask> using the default method. It will type-check correctly because we have a <hask>Generic</hask> instance for <hask>UserTree</hask>, and <hask>GSerialize</hask> instances for all the representation types.<br />
<br />
== Different perspectives ==<br />
<br />
We outline the changes introduced in 7.2 regarding support for generic programming from the perspective of three different types of users: the end-user, the generic programmer, and the GHC hacker.<br />
<br />
=== The end-user ===<br />
<br />
If you know nothing about generic programming and would like to keep it that way, then you will be pleased to know that using generics in GHC 7.2 is easier than ever. As soon as you encounter a class with a default signature (like <tt>Serialize</tt> above), you will be able to give empty instances for your datatypes, like this:<br />
<br />
<haskell><br />
instance (Serialize a) => Serialize (UserTree a)<br />
</haskell><br />
<br />
You will need to add a <hask>deriving Generic</hask> clause to each datatype that you want to have generic implementations for. You might have datatypes that use other datatypes, and you might need <tt>Generic</tt> instances for those too. In that case, you can import the module where the datatype is defined and give a standalone deriving <tt>Generic</tt> instance. In either case, you will need the <tt>-XDeriveGeneric</tt> flag.<br />
<br />
=== The generic programmer ===<br />
<br />
If you are a library author and are eager to make your classes easy to instantiate by your users, then you should invest some time in defining instances for each of the representation types of <tt>GHC.Generics</tt> and defining a generic default method. See the example for <tt>Serialize</tt> above, and the [http://dreixel.net/research/pdf/gdmh.pdf original paper] for many other examples (but make sure to check the [[#Changes from the paper|changes from the paper]]).<br />
<br />
=== The GHC hacker ===<br />
<br />
If you are working on the GHC source code, you might find it useful to know what kind of changes were made. There is a [http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving Trac wiki page] with a lower-level overview of things and also keeping track of what still needs to be done.<br />
<br />
== Changes from the paper ==<br />
<br />
In the [http://dreixel.net/research/pdf/gdmh.pdf paper] we describe the implementation in [http://www.cs.uu.nl/wiki/UHC UHC]. The implementation in GHC is slightly different:<br />
<br />
* <tt>Representable0</tt> and <tt>Representable1</tt> have become <tt>Generic</tt> and <tt>Generic1</tt>, respectively. <tt>from0</tt>, <tt>to0</tt>, and <tt>Rep0</tt> also lost the <tt>0</tt> at the end of their names.<br />
<br />
* We are using type families, so the <tt>Generic</tt> and <tt>Generic1</tt> type classes have only one type argument. So, in GHC the classes look like what we describe in the "Avoiding extensions" part of Section 2.3 of the paper. This change affects only a generic function writer, and not a generic function user.<br />
<br />
* Default definitions (Section 3.3) work differently. In GHC we don't use a <tt>DERIVABLE</tt> pragma; instead, a type class can declare a ''generic default method'', which is akin to a standard default method, but includes a default type signature. This removes the need for a separate default definition and a pragma. For example, the <tt>Encode</tt> class of Section 3.1 is now:<br />
<haskell><br />
class Encode a where<br />
encode :: a -> [Bit]<br />
default encode :: (Generic a, Encode1 (Rep a)) => a -> [Bit]<br />
encode = encode1 . from<br />
</haskell><br />
<br />
* To derive generic functionality to a user type, the user no longer uses <hask>deriving instance</hask> (Section 4.6.1). Instead, the user gives an instance without defining the method; GHC then uses the generic default. For instance:<br />
<haskell><br />
instance Encode [a] -- works if there is an instance Generic [a]<br />
</haskell><br />
<br />
== Limitations ==<br />
<br />
We cannot derive <tt>Generic</tt> instances for:<br />
* Datatypes with a context;<br />
* Existentially-quantified datatypes;<br />
* GADTs.<br />
<br />
<br />
[[Category:GHC]]<br />
[[Category:Language extensions]]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Applications_and_libraries/GUI_libraries&diff=48195Applications and libraries/GUI libraries2012-08-10T14:54:14Z<p>Amy de B: /* vty-ui */</p>
<hr />
<div>[[Category:User interfaces]]<br />
{{unknown copyright}}<br />
{{LibrariesPage}}<br />
<br />
There is a large number of GUI libraries for Haskell. Unfortunately there is no standard one and all are more or less incomplete. In general, low-level veneers are going well, but they are low level. High-level abstractions are pretty experimental. There is a need for a supported medium-level GUI library.<br />
<br />
== High-level ==<br />
<br />
=== FG ===<br />
<br />
FG is an arrow-based high-level functional approach to composable GUIs, built on top of Gtk2Hs. It is inspired by Fruit but uses discrete events instead of continuous signals.<br />
<br />
See the [http://kevin.atkinson.dhs.org/fg/doc/FG.html FG homepage].<br />
<br />
=== FranTk ===<br />
<br />
FranTk is a library (that seems to have disappeared from Internet) for building GUIs in Haskell. FranTk uses behaviours and events, concepts from Conal Elliott’s Functional Reactive Animation. FranTk provides good support for developing complex dynamic systems, and is built on top of Tcl/Tk. This makes it platform independent. FranTk was developed by [http://www.dcs.gla.ac.uk/~meurig/ Meurig Sage]. It runs on Unix and Windows.<br />
<br />
A short description can be found at the <br />
[http://src.gnu-darwin.org/ports/x11-toolkits/hs-frantk/work/FranTk1.1/FranTk.html GNU-Darwin site]. For more information, see the PDF document [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.25.8446&rep=rep1&type=pdf FranTk – A declarative GUI language for Haskell].<br />
<br />
=== Fruit ===<br />
<br />
Fruit is another high-level approach to GUIs in Haskell. It is based on the concepts of Functional Reactive Programming and arrows. There is also another implementation of this approach, called wxFruit (see below).<br />
<br />
See the [http://www.haskell.org/fruit/ Fruit homepage].<br />
<br />
=== Fudgets ===<br />
Fudgets is primarily a Graphical User Interface Toolkit for Haskell and the X Windows system. Fudgets also makes it easy to create client-server applications that communicate via the Internet. It runs on Unix but not on Windows.<br />
<br />
See the [http://www.altocumulus.org/Fudgets/ homepage] and [http://www.altocumulus.org/Fudgets/springschool95-intro.html Programming with Fudgets] which is a short presentation of the Fudget Library and the ideas underlying it.<br />
<br />
=== Grapefruit ===<br />
<br />
Grapefruit is an arrow-based declarative library. Widgets, windows and control components communicate via discrete and continuous signals. The use of signals is explicit in the interface to avoid certain inefficiencies. Internally, Grapefruit uses the event handling mechanisms of the underlying GUI toolkit.<br />
<br />
Currently, Grapefruit is build on top of Gtk2Hs but implementations based on other toolkits are planned for the future.<br />
<br />
See [[Grapefruit]].<br />
<br />
=== GuiTV ===<br />
<br />
GuiTV is a small library for GUI-style visualizing functional values. It can also be viewed as an approach to functional GUIs. It is implemented very simply by using [[Phooey]] in the [[TV]] framework.<br />
<br />
See [[GuiTV]].<br />
<br />
=== Phooey === <br />
<br />
Phooey is simple, functional, arrow-based library. Currently it is implemented atop [[wxHaskell]]. Phooey supports dynamic input bounds, flexible layout, and mutually-referential widgets.<br />
<br />
See [[Phooey]].<br />
<br />
=== wxFruit ===<br />
<br />
[[wxFruit]] is a GUI library based on the ideas of Fruit but built on top of wxHaskell.<br />
<br />
== Data Binding ==<br />
<br />
[http://hackage.haskell.org/package/binding-core binding-core] is a framework for binding mutable data to IO objects. [http://hackage.haskell.org/package/binding-gtk binding-gtk] and [http://hackage.haskell.org/package/binding-wx binding-wx] provide convenient wrappers for [[Gtk2Hs]] and [[WxHaskell]] respectively.<br />
<br />
== Medium-level ==<br />
<br />
=== Functional Forms ===<br />
<br />
An addition to wxHaskell, Functional Forms is a combinator library/domain specific language which enables a very concise programming style for forms: dialogs which only show and edit a set of values. Forms are used in many applications as Options or Settings dialogs.<br />
<br />
See the [http://www.sandr.dds.nl/FunctionalForms Functional Forms homepage].<br />
<br />
=== Gtk2Hs ===<br />
<br />
Gtk2Hs is a GUI library for Haskell based on [http://www.gtk.org Gtk+]. Gtk+ is an extensive and mature multi-platform toolkit for creating graphical user interfaces. Gtk2Hs is actively developed, supporting the latest version of the Gtk+ 2.x series. It provides automatic memory management, Unicode support and also bindings for various Gnome modules. It runs on Windows, Linux, MacOS X, FreeBSD and Solaris.<br />
<br />
See [[Gtk2Hs]].<br />
<br />
=== HGL ===<br />
<br />
HGL is actually only a grapics library.<br />
<br />
See the [http://haskell.org/graphics/ HGL homepage].<br />
<br />
=== HQK ===<br />
<br />
HQK is an effort to provide Haskell bindings to large parts of the Qt and KDE libraries. The goal is to auto-generate most of the binding code from C++ header files. We plan to develop a HQK GUI backend for the Functional Reactive Programming library [[Grapefruit]], thereby making Grapefruit multi-platform.<br />
<br />
See [[HQK]].<br />
<br />
=== HTk ===<br />
<br />
Htk is a typed, portable encapsulation of Tcl/Tk into Haskell. Its distinctive features are the use of Haskell types and type classes for structuring the interface, an abstract notion of event for describing user interaction, and portability across Windows, Unix and Linux.<br />
<br />
See the [http://www.informatik.uni-bremen.de/htk HTk homepage].<br />
<br />
=== HToolkit ===<br />
<br />
HToolkit is a portable Haskell library for writing graphical user interfaces (GUI's). The library is built upon a low-level interface that will be implemented for each different target platform. The low-level library is called Port and is currently implemented for GTK and Windows. The middle-level library is named GIO (the Graphical IO library) and is built upon the low-level Port library.<br />
<br />
See the [http://htoolkit.sourceforge.net/ HToolkit homepage].<br />
<br />
=== Object I/O for Haskell ===<br />
<br />
This is a port of Clean Object I/O library for Haskell.<br />
<br />
See the [http://haskell.org/ObjectIO Object I/O for Haskell homepage].<br />
<br />
=== qtHaskell ===<br />
<br />
qtHaskell is a set of bindings for the Qt Widget library from Trolltech. Haskell<br />
programmers can now access the Qt "signals and slots" based interface methodolgy<br />
(no Qt precompilation necessary), runtime loading of xml based interfaces<br />
designed with Qt Designer, ECMA/Javascript based apps (signal/slot calls can be passed through from javascript to Haskell and vice/versa) and so on.<br />
<br />
Second preview version is downloadable from [http://qthaskell.berlios.de qtHaskell at Berlios].<br />
<br />
=== wxHaskell ===<br />
<br />
wxHaskell is a portable and native GUI library built on top of wxWidgets (formerly wxWindows)—a comprehensive C++ library that is portable across all major GUI platforms; including GTK, Windows, X11, and MacOS X. wxWidgets is a mature library (in development since 1992) that supports a wide range of widgets with the native look-and-feel, and it has a very active community.<br />
<br />
See [[wxHaskell]].<br />
<br />
== Low-level ==<br />
<br />
=== GLFW ===<br />
<br />
This is a binding to the [http://glfw.sourceforge.net GLFW OpenGL framework]. It provides an alternative to GLUT for OpenGL based Haskell programs.<br />
<br />
See [[GLFW]].<br />
<br />
=== GLUT ===<br />
<br />
This is a binding to the OpenGL GLUT library.<br />
<br />
=== TclHaskell ===<br />
<br />
TclHaskell is a library of functions for writing platform independent, graphical user interfaces in Haskell. The library provides a convenient, abstract and high-level way to write window-oriented applications. It also provides a more low level interface to write primitive Tcl code where helpful. For Unix and Windows and maybe Macintosh.<br />
<br />
See the [http://www.dcs.gla.ac.uk/~meurig/TclHaskell/ TclHaskell homepage].<br />
<br />
=== Win32 ===<br />
<br />
A binding to parts of the Win32 API.<br />
<br />
=== X11 ===<br />
<br />
A binding to parts of the X11 libraries.<br />
<br />
== Uncategorized ==<br />
<br />
=== Nanocurses ===<br />
<br />
Nanocurses is a minimal binding to curses and ncurses. It is smaller than hscurses and has less features. It also provides fast packed string support. It provides a Curses.hsc derived from Hmp3.<br />
<br />
See the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/nanocurses Hackage page].<br />
<br />
=== hscurses ===<br />
<br />
This is a Haskell binding to the NCurses library, a library of functions that manage an application’s display on character-cell terminals. hscurses also provides some basic widgets implemented on top of the ncurses binding, such as a text input widget and a table widget.<br />
<br />
See the [http://www.stefanwehr.de/software/#hscurses hscurses homepage].<br />
<br />
=== vty ===<br />
<br />
Another text-based UI library; attempts to be easy to use.<br />
<br />
See the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/vty Hackage page].<br />
<br />
=== vty-ui ===<br />
<br />
[http://jtdaugherty.github.com/vty-ui/ vty-ui] is a<br />
high-level user interface library for applications running in terminal emulators. It provides similar functionality to what you might expect from graphical toolkits like GTK and QT. vty-ui is written in the Haskell programming language.<br />
<br />
== Unsupported ==<br />
<br />
The following libraries seem to be no longer maintained. However, someone might pick up one of them or at least profit from some design ideas.<br />
<br />
=== AutoForms ===<br />
<br />
[[AutoForms]] is a library to ease the creation of Graphical User Interfaces (GUI). It does this by using generic programming to construct GUI components.<br />
<br />
=== Budgets ===<br />
<br />
Budgets is a library of Fudget-like combinators based on the Openlook widget library was developed by Alastair Reid and Satnam Singh. The code has suffered tremendous bit-rot (Does anyone have a copy of ghc-0.16?) but all the reusable ideas are described in the [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.19.3342&rep=rep1&type=pdf respective paper].<br />
<br />
<br />
=== Embracing Windows ===<br />
<br />
This is a framework for developing graphical user interfaces. It runs under Windows 95 using a modified version of Hugs 1.3.<br />
<br />
See the [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.55.2958&rep=rep1&type=pdf Embracing Windows paper] (PDF).<br />
<br />
=== Gadgets ===<br />
<br />
Gadgets are lazy functional components for graphical user interfaces, developed by Rob Noble under the supervision of [http://www.cs.york.ac.uk/~colin/ Colin Runciman].<br />
<br />
See LNCS 982, pages 321-340.<br />
<br />
=== Gtk+HS ===<br />
<br />
Gtk+HS is a Haskell binding for GTK+. It provides a transcription of the original GTK+ API into Haskell. GTK+ is a modern, portable GUI library and forms the basis of the Gnome desktop project. The binding, while not complete, covers most of GTK+'s core functionality and is ready for use in applications that require a GUI of medium complexity. It was developed under Unix, but should also be usable with the Windows port of GTK+.<br />
<br />
See the [http://www.cse.unsw.edu.au/~chak/haskell/gtk/ Gtk+HS homepage].<br />
<br />
=== Haggis ===<br />
<br />
Haggis is a graphical user interface framework for Haskell, running under the X Window system. It is being developed using the Glasgow Haskell Compiler with its concurrent extensions to achieve more comfortable interaction with the outside world.<br />
<br />
See the [http://www.dcs.gla.ac.uk/fp/software/haggis/ Haggis homepage].<br />
<br />
=== iHaskell ===<br />
<br />
iHaskell is a functional wrapper on top of GTK+HS that provides convenience functions for frequently used programming patterns, and eliminates the need for explicit mutable variables.<br />
<br />
See the [http://www.cse.unsw.edu.au/~chak/haskell/gtk/#iHaskell iHaskell homepage].<br />
<br />
=== Pidgets ===<br />
<br />
Pidgets, developed by [http://www.informatik.uni-trier.de/~ley/db/indices/a-tree/s/Scholz:Enno.html Enno Scholz], unifies pictures and widgets in a constraint-based framework for concurrent functional GUI programming.<br />
<br />
== Hackage ==<br />
<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:interfaces User interface libraries on Hackage]<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:graphics Graphics libraries on Hackage]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Applications_and_libraries/GUI_libraries&diff=48194Applications and libraries/GUI libraries2012-08-10T14:50:55Z<p>Amy de B: /* vty */</p>
<hr />
<div>[[Category:User interfaces]]<br />
{{unknown copyright}}<br />
{{LibrariesPage}}<br />
<br />
There is a large number of GUI libraries for Haskell. Unfortunately there is no standard one and all are more or less incomplete. In general, low-level veneers are going well, but they are low level. High-level abstractions are pretty experimental. There is a need for a supported medium-level GUI library.<br />
<br />
== High-level ==<br />
<br />
=== FG ===<br />
<br />
FG is an arrow-based high-level functional approach to composable GUIs, built on top of Gtk2Hs. It is inspired by Fruit but uses discrete events instead of continuous signals.<br />
<br />
See the [http://kevin.atkinson.dhs.org/fg/doc/FG.html FG homepage].<br />
<br />
=== FranTk ===<br />
<br />
FranTk is a library (that seems to have disappeared from Internet) for building GUIs in Haskell. FranTk uses behaviours and events, concepts from Conal Elliott’s Functional Reactive Animation. FranTk provides good support for developing complex dynamic systems, and is built on top of Tcl/Tk. This makes it platform independent. FranTk was developed by [http://www.dcs.gla.ac.uk/~meurig/ Meurig Sage]. It runs on Unix and Windows.<br />
<br />
A short description can be found at the <br />
[http://src.gnu-darwin.org/ports/x11-toolkits/hs-frantk/work/FranTk1.1/FranTk.html GNU-Darwin site]. For more information, see the PDF document [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.25.8446&rep=rep1&type=pdf FranTk – A declarative GUI language for Haskell].<br />
<br />
=== Fruit ===<br />
<br />
Fruit is another high-level approach to GUIs in Haskell. It is based on the concepts of Functional Reactive Programming and arrows. There is also another implementation of this approach, called wxFruit (see below).<br />
<br />
See the [http://www.haskell.org/fruit/ Fruit homepage].<br />
<br />
=== Fudgets ===<br />
Fudgets is primarily a Graphical User Interface Toolkit for Haskell and the X Windows system. Fudgets also makes it easy to create client-server applications that communicate via the Internet. It runs on Unix but not on Windows.<br />
<br />
See the [http://www.altocumulus.org/Fudgets/ homepage] and [http://www.altocumulus.org/Fudgets/springschool95-intro.html Programming with Fudgets] which is a short presentation of the Fudget Library and the ideas underlying it.<br />
<br />
=== Grapefruit ===<br />
<br />
Grapefruit is an arrow-based declarative library. Widgets, windows and control components communicate via discrete and continuous signals. The use of signals is explicit in the interface to avoid certain inefficiencies. Internally, Grapefruit uses the event handling mechanisms of the underlying GUI toolkit.<br />
<br />
Currently, Grapefruit is build on top of Gtk2Hs but implementations based on other toolkits are planned for the future.<br />
<br />
See [[Grapefruit]].<br />
<br />
=== GuiTV ===<br />
<br />
GuiTV is a small library for GUI-style visualizing functional values. It can also be viewed as an approach to functional GUIs. It is implemented very simply by using [[Phooey]] in the [[TV]] framework.<br />
<br />
See [[GuiTV]].<br />
<br />
=== Phooey === <br />
<br />
Phooey is simple, functional, arrow-based library. Currently it is implemented atop [[wxHaskell]]. Phooey supports dynamic input bounds, flexible layout, and mutually-referential widgets.<br />
<br />
See [[Phooey]].<br />
<br />
=== wxFruit ===<br />
<br />
[[wxFruit]] is a GUI library based on the ideas of Fruit but built on top of wxHaskell.<br />
<br />
== Data Binding ==<br />
<br />
[http://hackage.haskell.org/package/binding-core binding-core] is a framework for binding mutable data to IO objects. [http://hackage.haskell.org/package/binding-gtk binding-gtk] and [http://hackage.haskell.org/package/binding-wx binding-wx] provide convenient wrappers for [[Gtk2Hs]] and [[WxHaskell]] respectively.<br />
<br />
== Medium-level ==<br />
<br />
=== Functional Forms ===<br />
<br />
An addition to wxHaskell, Functional Forms is a combinator library/domain specific language which enables a very concise programming style for forms: dialogs which only show and edit a set of values. Forms are used in many applications as Options or Settings dialogs.<br />
<br />
See the [http://www.sandr.dds.nl/FunctionalForms Functional Forms homepage].<br />
<br />
=== Gtk2Hs ===<br />
<br />
Gtk2Hs is a GUI library for Haskell based on [http://www.gtk.org Gtk+]. Gtk+ is an extensive and mature multi-platform toolkit for creating graphical user interfaces. Gtk2Hs is actively developed, supporting the latest version of the Gtk+ 2.x series. It provides automatic memory management, Unicode support and also bindings for various Gnome modules. It runs on Windows, Linux, MacOS X, FreeBSD and Solaris.<br />
<br />
See [[Gtk2Hs]].<br />
<br />
=== HGL ===<br />
<br />
HGL is actually only a grapics library.<br />
<br />
See the [http://haskell.org/graphics/ HGL homepage].<br />
<br />
=== HQK ===<br />
<br />
HQK is an effort to provide Haskell bindings to large parts of the Qt and KDE libraries. The goal is to auto-generate most of the binding code from C++ header files. We plan to develop a HQK GUI backend for the Functional Reactive Programming library [[Grapefruit]], thereby making Grapefruit multi-platform.<br />
<br />
See [[HQK]].<br />
<br />
=== HTk ===<br />
<br />
Htk is a typed, portable encapsulation of Tcl/Tk into Haskell. Its distinctive features are the use of Haskell types and type classes for structuring the interface, an abstract notion of event for describing user interaction, and portability across Windows, Unix and Linux.<br />
<br />
See the [http://www.informatik.uni-bremen.de/htk HTk homepage].<br />
<br />
=== HToolkit ===<br />
<br />
HToolkit is a portable Haskell library for writing graphical user interfaces (GUI's). The library is built upon a low-level interface that will be implemented for each different target platform. The low-level library is called Port and is currently implemented for GTK and Windows. The middle-level library is named GIO (the Graphical IO library) and is built upon the low-level Port library.<br />
<br />
See the [http://htoolkit.sourceforge.net/ HToolkit homepage].<br />
<br />
=== Object I/O for Haskell ===<br />
<br />
This is a port of Clean Object I/O library for Haskell.<br />
<br />
See the [http://haskell.org/ObjectIO Object I/O for Haskell homepage].<br />
<br />
=== qtHaskell ===<br />
<br />
qtHaskell is a set of bindings for the Qt Widget library from Trolltech. Haskell<br />
programmers can now access the Qt "signals and slots" based interface methodolgy<br />
(no Qt precompilation necessary), runtime loading of xml based interfaces<br />
designed with Qt Designer, ECMA/Javascript based apps (signal/slot calls can be passed through from javascript to Haskell and vice/versa) and so on.<br />
<br />
Second preview version is downloadable from [http://qthaskell.berlios.de qtHaskell at Berlios].<br />
<br />
=== wxHaskell ===<br />
<br />
wxHaskell is a portable and native GUI library built on top of wxWidgets (formerly wxWindows)—a comprehensive C++ library that is portable across all major GUI platforms; including GTK, Windows, X11, and MacOS X. wxWidgets is a mature library (in development since 1992) that supports a wide range of widgets with the native look-and-feel, and it has a very active community.<br />
<br />
See [[wxHaskell]].<br />
<br />
== Low-level ==<br />
<br />
=== GLFW ===<br />
<br />
This is a binding to the [http://glfw.sourceforge.net GLFW OpenGL framework]. It provides an alternative to GLUT for OpenGL based Haskell programs.<br />
<br />
See [[GLFW]].<br />
<br />
=== GLUT ===<br />
<br />
This is a binding to the OpenGL GLUT library.<br />
<br />
=== TclHaskell ===<br />
<br />
TclHaskell is a library of functions for writing platform independent, graphical user interfaces in Haskell. The library provides a convenient, abstract and high-level way to write window-oriented applications. It also provides a more low level interface to write primitive Tcl code where helpful. For Unix and Windows and maybe Macintosh.<br />
<br />
See the [http://www.dcs.gla.ac.uk/~meurig/TclHaskell/ TclHaskell homepage].<br />
<br />
=== Win32 ===<br />
<br />
A binding to parts of the Win32 API.<br />
<br />
=== X11 ===<br />
<br />
A binding to parts of the X11 libraries.<br />
<br />
== Uncategorized ==<br />
<br />
=== Nanocurses ===<br />
<br />
Nanocurses is a minimal binding to curses and ncurses. It is smaller than hscurses and has less features. It also provides fast packed string support. It provides a Curses.hsc derived from Hmp3.<br />
<br />
See the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/nanocurses Hackage page].<br />
<br />
=== hscurses ===<br />
<br />
This is a Haskell binding to the NCurses library, a library of functions that manage an application’s display on character-cell terminals. hscurses also provides some basic widgets implemented on top of the ncurses binding, such as a text input widget and a table widget.<br />
<br />
See the [http://www.stefanwehr.de/software/#hscurses hscurses homepage].<br />
<br />
=== vty ===<br />
<br />
Another text-based UI library; attempts to be easy to use.<br />
<br />
See the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/vty Hackage page].<br />
<br />
=== vty-ui ===<br />
<br />
A high-level user interface library for applications running in terminal emulators. It provides similar functionality to what you might expect from graphical toolkits like GTK and QT. vty-ui is written in the Haskell programming language.<br />
<br />
== Unsupported ==<br />
<br />
The following libraries seem to be no longer maintained. However, someone might pick up one of them or at least profit from some design ideas.<br />
<br />
=== AutoForms ===<br />
<br />
[[AutoForms]] is a library to ease the creation of Graphical User Interfaces (GUI). It does this by using generic programming to construct GUI components.<br />
<br />
=== Budgets ===<br />
<br />
Budgets is a library of Fudget-like combinators based on the Openlook widget library was developed by Alastair Reid and Satnam Singh. The code has suffered tremendous bit-rot (Does anyone have a copy of ghc-0.16?) but all the reusable ideas are described in the [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.19.3342&rep=rep1&type=pdf respective paper].<br />
<br />
<br />
=== Embracing Windows ===<br />
<br />
This is a framework for developing graphical user interfaces. It runs under Windows 95 using a modified version of Hugs 1.3.<br />
<br />
See the [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.55.2958&rep=rep1&type=pdf Embracing Windows paper] (PDF).<br />
<br />
=== Gadgets ===<br />
<br />
Gadgets are lazy functional components for graphical user interfaces, developed by Rob Noble under the supervision of [http://www.cs.york.ac.uk/~colin/ Colin Runciman].<br />
<br />
See LNCS 982, pages 321-340.<br />
<br />
=== Gtk+HS ===<br />
<br />
Gtk+HS is a Haskell binding for GTK+. It provides a transcription of the original GTK+ API into Haskell. GTK+ is a modern, portable GUI library and forms the basis of the Gnome desktop project. The binding, while not complete, covers most of GTK+'s core functionality and is ready for use in applications that require a GUI of medium complexity. It was developed under Unix, but should also be usable with the Windows port of GTK+.<br />
<br />
See the [http://www.cse.unsw.edu.au/~chak/haskell/gtk/ Gtk+HS homepage].<br />
<br />
=== Haggis ===<br />
<br />
Haggis is a graphical user interface framework for Haskell, running under the X Window system. It is being developed using the Glasgow Haskell Compiler with its concurrent extensions to achieve more comfortable interaction with the outside world.<br />
<br />
See the [http://www.dcs.gla.ac.uk/fp/software/haggis/ Haggis homepage].<br />
<br />
=== iHaskell ===<br />
<br />
iHaskell is a functional wrapper on top of GTK+HS that provides convenience functions for frequently used programming patterns, and eliminates the need for explicit mutable variables.<br />
<br />
See the [http://www.cse.unsw.edu.au/~chak/haskell/gtk/#iHaskell iHaskell homepage].<br />
<br />
=== Pidgets ===<br />
<br />
Pidgets, developed by [http://www.informatik.uni-trier.de/~ley/db/indices/a-tree/s/Scholz:Enno.html Enno Scholz], unifies pictures and widgets in a constraint-based framework for concurrent functional GUI programming.<br />
<br />
== Hackage ==<br />
<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:interfaces User interface libraries on Hackage]<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:graphics Graphics libraries on Hackage]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Yi/FAQ&diff=48020Yi/FAQ2012-08-07T16:34:24Z<p>Amy de B: /* Development */</p>
<hr />
<div>=== Installation ===<br />
<br />
*How do I install Yi?<br />
:get it from Hackage. Configure, compile and install Yi as you would do for any other Cabal package.<br />
<br />
*Setup configure fails with <br />
Setup.hs: Package yi-0.4 can't be built on this system.<br />
:It means that you have no UI package available. You need VTY or GTK2hs installed. Get them from Hackage.<br />
<br />
*cabal install yi fails with dependency errors, eg:<br />
$ cabal install yi<br />
Resolving dependencies...<br />
cabal.exe: dependencies conflict: ghc-6.8.3 requires bytestring ==0.9.0.1.1<br />
however<br />
bytestring-0.9.0.1.1 was excluded because bytestring-0.9.0.1 was selected<br />
instead<br />
bytestring-0.9.0.1.1 was excluded because yi-0.3 requires bytestring =0.9.0.1<br />
:Try removing all your old yi packages, and do<br />
cabal update<br />
before attempting to install.<br />
<br />
*cabal install -fghcAPI fails<br />
:If you want GHC API special capabilities, you have to download, configure, build and copy separately:<br />
cd yi<br />
cabal configure -fghcAPI<br />
cabal build<br />
cabal copy<br />
<br />
* Compilation fails with a message about <tt>alex</tt> not being available?<br />
: Currently, Cabal doesn't track programs, just libraries, so it won't warn you if you are missing Alex (as many people are). The solution here is to just <tt>cabal install alex</tt> first. (Yi uses Alex to generate code for parsing stuff with syntax, like Haskell source.)<br />
<br />
* I can't install <tt>yi-gtk</tt> or <tt>yi-vty</tt>! It wants <tt>sourceview</tt> or something.<br />
: As the Hackage descriptions say, yi-gtk and yi-vty are ''only'' for versions of older than Yi 0.3. You really should be running the latest development (Darcs) or stable (Hackage) versions of Yi, so ''don't'' try to install these two packages. Yi supports VTY and Gtk2hs directly in the <tt>yi</tt> package now.<br />
*On Mac OS X if you get an error message similar to this:<br />
yi: can't load .so/.DLL for: gthread-2.0 (dlopen(libgthread-2.0.dylib, 10): image not found)<br />
<br />
:then your dynamic library search path variable is probably not set correctly. You can set it (in Bash) using:<br />
<br />
export DYLD_LIBRARY_PATH=/opt/local/lib<br />
<br />
:(Adjust the specific path to your system. You can find the right location using <tt>locate libgthread</tt>)<br />
<br />
*On Mac OS 10.6 (Snow Leopard) if you get the following error:<br />
Loading package cairo-0.11.1 ... <command line>: can't load .so/.DLL for: pixman-1 (dlopen(/opt/local/lib/libpixman-1.dylib, 9): no suitable image found. Did find:<br />
/opt/local/lib/libpixman-1.dylib: mach-o, but wrong architecture)<br />
cabal: Error: some packages failed to install:<br />
yi-0.6.2.4 failed during the building phase. The exception was:<br />
ExitFailure 1<br />
<br />
:then the problem is that GHC currently only supports linking against i386 libraries, and your ports are compiled for x86_64. To fix, recompile your ports with the +universal variant like so:<br />
<br />
port install installed +universal<br />
<br />
* Compilation fails with errors about template-haskell or data-accessor:<br />
Add constraints about which release of those libraries to use.<br />
$ cabal install yi --constraint="data-accessor < 0.2.1" --constraint="template-haskell < 2.4"<br />
<br />
<br />
=== Default key bindings ===<br />
<br />
==== CUA key bindings ====<br />
<br />
===== File operations =====<br />
{|<br />
| Ctrl-o<br />
| Open file.<br />
|-<br />
| Ctrl-s<br />
| Save the current file.<br />
|-<br />
| Ctrl-q<br />
| Quit the editor.<br />
|}<br />
<br />
===== Cursor/selection movement =====<br />
{|<br />
| &rarr;<br />
| Move cursor forward one character.<br />
|-<br />
| &larr;<br />
| Move cursor back one character.<br />
|-<br />
| &darr;<br />
| Move cursor down one line.<br />
|-<br />
| &uarr;<br />
| Move cursor down one line.<br />
|-<br />
| Shift+&rarr;<br />
| Extend selection forward one character.<br />
|-<br />
| Shift+&larr;<br />
| Extend selection back one character.<br />
|-<br />
| Shift+&darr;<br />
| Extend selection down one line.<br />
|-<br />
| Shift+&uarr;<br />
| Extend selection up one line.<br />
|-<br />
| Ctrl-&rarr;<br />
| Move cursor forward one word.<br />
|-<br />
| Ctrl-&larr;<br />
| Move cursor back one word.<br />
|-<br />
| Home<br />
| Move cursor to beginning of line.<br />
|-<br />
| End<br />
| Move cursor to end of line.<br />
|-<br />
| Ctrl-Home<br />
| Move cursor to beginning of document.<br />
|-<br />
| Ctrl-End<br />
| Move cursor to end of document.<br />
|}<br />
<br />
===== Miscellaneous operations =====<br />
<br />
{|<br />
| Ctrl-f<br />
| Incremental search.<br />
|-<br />
| Ctrl-x<br />
| Cut the selected area and save it to the clipboard<br />
|-<br />
| Ctrl-c<br />
| Copy the selected area to the clipboard<br />
|-<br />
| Ctrl-v<br />
| Paste contents of clipboard at cursor.<br />
|-<br />
| Ctrl-z<br />
| Undo last operation.<br />
|-<br />
| Ctrl-y<br />
| Redo last operation.<br />
|}<br />
<br />
==== Vim key bindings ====<br />
==== Emacs key bindings ====<br />
<br />
=== Development ===<br />
<br />
*How do I install Yi for development?<br />
:Fork the repository on GitHub, then clone your version to your machine. Push to your repo on GitHub, and then make merge requests.<br />
<br />
*What are some of the dependancies?<br />
:There is a rather long list of dependencies for Yi, check the yi.cabal file for a list.<br />
<br />
::If you are on Mac OS X and are using MacPorts, then these will not be included in the GHC in that distribution. Many of the dependancies are in MacPorts (for example: ghc, ghc-devel, alex, and gtk2hs). However, you may have some trouble building with Cabal-1.5.2, since it is a development version of Cabal. To work around these issues, you might have to add the line "Build-Type: Simple" to the .cabal files in the above required packages.<br />
<br />
=== Configuration ===<br />
<br />
==== How to Configure Yi ====<br />
<br />
You can find configuration file examples in the 'examples/' directory, or online at [http://code.haskell.org/yi/examples/ http://code.haskell.org/yi/examples/].<br />
<br />
A good way to start is to copy yi.hs in your ~/.yi directory (create it if needed), and hack as needed.<br />
=== Usage ===<br />
==== GError on startup ====<br />
I get the error message "yi.exe: <<System.Glib.GError.GError>>" when I try to run yi.<br />
<br />
Sometimes this is a result of yi not being able to find the contents of the art directory when trying to start in graphical mode (e.g. Gtk or Pango). Check that the install has be done correctly or use the VTY mode (<tt>$ yi -f vty</tt>).<br />
<br />
For more detail on the error, modify main in Yi/Main.hs to catch GError:<br />
<pre><br />
Right finalCfg -> do catchGError (do<br />
when (debugMode finalCfg) $ initDebug ".yi.dbg" <br />
startEditor finalCfg state) (\(GError dom code msg) -> fail msg)<br />
</pre><br />
<br />
Note that more recent versions of Yi (e.g. from the darcs repo) no longer simply display the anonymous GError but instead provide a more detailed error message (making the above code snippet unnecessary).</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Yi/FAQ&diff=48019Yi/FAQ2012-08-07T16:32:36Z<p>Amy de B: Documented key bindings</p>
<hr />
<div>=== Installation ===<br />
<br />
*How do I install Yi?<br />
:get it from Hackage. Configure, compile and install Yi as you would do for any other Cabal package.<br />
<br />
*Setup configure fails with <br />
Setup.hs: Package yi-0.4 can't be built on this system.<br />
:It means that you have no UI package available. You need VTY or GTK2hs installed. Get them from Hackage.<br />
<br />
*cabal install yi fails with dependency errors, eg:<br />
$ cabal install yi<br />
Resolving dependencies...<br />
cabal.exe: dependencies conflict: ghc-6.8.3 requires bytestring ==0.9.0.1.1<br />
however<br />
bytestring-0.9.0.1.1 was excluded because bytestring-0.9.0.1 was selected<br />
instead<br />
bytestring-0.9.0.1.1 was excluded because yi-0.3 requires bytestring =0.9.0.1<br />
:Try removing all your old yi packages, and do<br />
cabal update<br />
before attempting to install.<br />
<br />
*cabal install -fghcAPI fails<br />
:If you want GHC API special capabilities, you have to download, configure, build and copy separately:<br />
cd yi<br />
cabal configure -fghcAPI<br />
cabal build<br />
cabal copy<br />
<br />
* Compilation fails with a message about <tt>alex</tt> not being available?<br />
: Currently, Cabal doesn't track programs, just libraries, so it won't warn you if you are missing Alex (as many people are). The solution here is to just <tt>cabal install alex</tt> first. (Yi uses Alex to generate code for parsing stuff with syntax, like Haskell source.)<br />
<br />
* I can't install <tt>yi-gtk</tt> or <tt>yi-vty</tt>! It wants <tt>sourceview</tt> or something.<br />
: As the Hackage descriptions say, yi-gtk and yi-vty are ''only'' for versions of older than Yi 0.3. You really should be running the latest development (Darcs) or stable (Hackage) versions of Yi, so ''don't'' try to install these two packages. Yi supports VTY and Gtk2hs directly in the <tt>yi</tt> package now.<br />
*On Mac OS X if you get an error message similar to this:<br />
yi: can't load .so/.DLL for: gthread-2.0 (dlopen(libgthread-2.0.dylib, 10): image not found)<br />
<br />
:then your dynamic library search path variable is probably not set correctly. You can set it (in Bash) using:<br />
<br />
export DYLD_LIBRARY_PATH=/opt/local/lib<br />
<br />
:(Adjust the specific path to your system. You can find the right location using <tt>locate libgthread</tt>)<br />
<br />
*On Mac OS 10.6 (Snow Leopard) if you get the following error:<br />
Loading package cairo-0.11.1 ... <command line>: can't load .so/.DLL for: pixman-1 (dlopen(/opt/local/lib/libpixman-1.dylib, 9): no suitable image found. Did find:<br />
/opt/local/lib/libpixman-1.dylib: mach-o, but wrong architecture)<br />
cabal: Error: some packages failed to install:<br />
yi-0.6.2.4 failed during the building phase. The exception was:<br />
ExitFailure 1<br />
<br />
:then the problem is that GHC currently only supports linking against i386 libraries, and your ports are compiled for x86_64. To fix, recompile your ports with the +universal variant like so:<br />
<br />
port install installed +universal<br />
<br />
* Compilation fails with errors about template-haskell or data-accessor:<br />
Add constraints about which release of those libraries to use.<br />
$ cabal install yi --constraint="data-accessor < 0.2.1" --constraint="template-haskell < 2.4"<br />
<br />
<br />
=== Default key bindings ===<br />
<br />
==== CUA key bindings ====<br />
<br />
===== File operations =====<br />
{|<br />
| Ctrl-o<br />
| Open file.<br />
|-<br />
| Ctrl-s<br />
| Save the current file.<br />
|-<br />
| Ctrl-q<br />
| Quit the editor.<br />
|}<br />
<br />
===== Cursor/selection movement =====<br />
{|<br />
| &rarr;<br />
| Move cursor forward one character.<br />
|-<br />
| &larr;<br />
| Move cursor back one character.<br />
|-<br />
| &darr;<br />
| Move cursor down one line.<br />
|-<br />
| &uarr;<br />
| Move cursor down one line.<br />
|-<br />
| Shift+&rarr;<br />
| Extend selection forward one character.<br />
|-<br />
| Shift+&larr;<br />
| Extend selection back one character.<br />
|-<br />
| Shift+&darr;<br />
| Extend selection down one line.<br />
|-<br />
| Shift+&uarr;<br />
| Extend selection up one line.<br />
|-<br />
| Ctrl-&rarr;<br />
| Move cursor forward one word.<br />
|-<br />
| Ctrl-&larr;<br />
| Move cursor back one word.<br />
|-<br />
| Home<br />
| Move cursor to beginning of line.<br />
|-<br />
| End<br />
| Move cursor to end of line.<br />
|-<br />
| Ctrl-Home<br />
| Move cursor to beginning of document.<br />
|-<br />
| Ctrl-End<br />
| Move cursor to end of document.<br />
|}<br />
<br />
===== Miscellaneous operations =====<br />
<br />
{|<br />
| Ctrl-f<br />
| Incremental search.<br />
|-<br />
| Ctrl-x<br />
| Cut the selected area and save it to the clipboard<br />
|-<br />
| Ctrl-c<br />
| Copy the selected area to the clipboard<br />
|-<br />
| Ctrl-v<br />
| Paste contents of clipboard at cursor.<br />
|-<br />
| Ctrl-z<br />
| Undo last operation.<br />
|-<br />
| Ctrl-y<br />
| Redo last operation.<br />
|}<br />
<br />
==== Vim key bindings ====<br />
==== Emacs key bindings ====<br />
<br />
==== Development ====<br />
<br />
*How do I install Yi for development?<br />
:Fork the repository on GitHub, then clone your version to your machine. Push to your repo on GitHub, and then make merge requests.<br />
<br />
*What are some of the dependancies?<br />
:There is a rather long list of dependencies for Yi, check the yi.cabal file for a list.<br />
<br />
::If you are on Mac OS X and are using MacPorts, then these will not be included in the GHC in that distribution. Many of the dependancies are in MacPorts (for example: ghc, ghc-devel, alex, and gtk2hs). However, you may have some trouble building with Cabal-1.5.2, since it is a development version of Cabal. To work around these issues, you might have to add the line "Build-Type: Simple" to the .cabal files in the above required packages.<br />
<br />
=== Configuration ===<br />
<br />
==== How to Configure Yi ====<br />
<br />
You can find configuration file examples in the 'examples/' directory, or online at [http://code.haskell.org/yi/examples/ http://code.haskell.org/yi/examples/].<br />
<br />
A good way to start is to copy yi.hs in your ~/.yi directory (create it if needed), and hack as needed.<br />
=== Usage ===<br />
==== GError on startup ====<br />
I get the error message "yi.exe: <<System.Glib.GError.GError>>" when I try to run yi.<br />
<br />
Sometimes this is a result of yi not being able to find the contents of the art directory when trying to start in graphical mode (e.g. Gtk or Pango). Check that the install has be done correctly or use the VTY mode (<tt>$ yi -f vty</tt>).<br />
<br />
For more detail on the error, modify main in Yi/Main.hs to catch GError:<br />
<pre><br />
Right finalCfg -> do catchGError (do<br />
when (debugMode finalCfg) $ initDebug ".yi.dbg" <br />
startEditor finalCfg state) (\(GError dom code msg) -> fail msg)<br />
</pre><br />
<br />
Note that more recent versions of Yi (e.g. from the darcs repo) no longer simply display the anonymous GError but instead provide a more detailed error message (making the above code snippet unnecessary).</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Unicode-symbols&diff=42969Unicode-symbols2011-11-17T17:33:39Z<p>Amy de B: /* Vim */</p>
<hr />
<div>[[Category:Packages]]<br />
<br />
== Overview ==<br />
<br />
An overview of the packages that provide Unicode symbols. <br />
<br />
Naming: A package '''<tt>X-unicode-symbols</tt>''' defines new symbols for functions and operators from the package '''<tt>X</tt>'''.<br />
<br />
All symbols are documented with their actual definition and information regarding their Unicode code point. They should be completely interchangeable with their definitions.<br />
<br />
Alternatives for existing operators have the same fixity. New operators will have a suitable fixity defined.<br />
<br />
==== UnicodeSyntax ====<br />
<br />
GHC offers the [http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html#unicode-syntax UnicodeSyntax] language extension. If you decide to use Unicode in your Haskell source then this extension can greatly improve how it looks.<br />
<br />
Simply put the following above a module to enable unicode syntax:<br />
{-# LANGUAGE UnicodeSyntax #-}<br />
<br />
== base-unicode-symbols ==<br />
<br />
Extra symbols for the [http://hackage.haskell.org/package/base base] package.<br />
<br />
API docs: http://hackage.haskell.org/package/base-unicode-symbols<br />
github: https://github.com/roelvandijk/base-unicode-symbols<br />
checkout: git clone git://github.com/roelvandijk/base-unicode-symbols.git<br />
<br />
==== Problematic symbols ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| not<br />
| &#xAC;<br />
| U+AC<br />
| NOT SIGN<br />
|}<br />
The problem with this symbol is that you would like to use it as an unary prefix operator:<br />
&not;(&not;x) &equiv; x<br />
Unfortunately this is not valid Haskell. The following is:<br />
(&not;)((&not;)x) &equiv; x<br />
But you can hardly call that an improvement over the simple:<br />
not (not x) &equiv; x<br />
<br />
==== New symbol ideas ====<br />
(''please add your own'')<br />
<br />
I'm thinking of adding the following symbol as another alternative for (*).<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| (*)<br />
| &#xD7;<br />
| U+D7<br />
| MULTIPLICATION SIGN<br />
|}<br />
<br />
2 * 3 &equiv; 6<br />
2 &#x22C5; 3 &equiv; 6<br />
2 &#xD7; 3 &equiv; 6<br />
<br />
A disadvantage of this symbol is its similarity to the letter x:<br />
sqr x = x &#xD7; x<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Original<br />
! Symbol<br />
! Code point<br />
! Name<br />
|-<br />
| Bool<br />
| &#x1D539;<br />
| U+1D539<br />
| MATHEMATICAL DOUBLE-STRUCK CAPITAL B<br />
|}<br />
<br />
This idea is an extension of<br />
<br />
type &#x2115; = Integer<br />
<br />
and<br />
<br />
type &#x211A; = Ratio &#x2115;<br />
<br />
The advantage is that it looks nice and that it is a logical extension of &#x2115;, &#x211A; and &#x211D;. The disadvantage is that their is no documented prior use of this character to denote boolean values. This could be detrimental to the readability of code.<br />
<br />
Example:<br />
<br />
(&#x2227;) &#x2237; &#x1D539; &#x2192; &#x1D539; &#x2192; &#x1D539;<br />
<br />
== containers-unicode-symbols ==<br />
<br />
Extra symbols for the [http://hackage.haskell.org/package/containers containers] package.<br />
<br />
API docs: http://hackage.haskell.org/package/containers-unicode-symbols<br />
github: https://github.com/roelvandijk/containers-unicode-symbols<br />
checkout: git clone git://github.com/roelvandijk/containers-unicode-symbols.git <br />
<br />
==== New symbol ideas ==== <br />
(''please add your own'')<br />
<br />
== Input methods ==<br />
<br />
These symbols are all very nice but how do you type them?<br />
<br />
Wikipedia has a helpful article: http://en.wikipedia.org/wiki/Unicode_input<br />
<br />
(''please add info for other editors'')<br />
<br />
=== Emacs ===<br />
<br />
'''Direct'''<br />
<br />
Enter symbols directly: <tt>[http://www.gnu.org/software/emacs/manual/html_node/emacs/International-Chars.html C-x 8 RET]</tt> (<tt>ucs-insert</tt>), then type either the character's name or its hexadecimal code point.<br />
<br />
'''TeX input method'''<br />
<br />
The TeX input method, invoked with <tt>M-x set-input-method</tt> and entering <tt>TeX</tt> allows you to enter Unicode characters by typing in TeX-like sequences. For example, typing <tt>\lambda</tt> inserts a λ.<br />
<br />
This is probably the most convenient input method for casual use.<br />
<br />
A list of available sequences may be viewed with <tt>M-x describe-input-method</tt><br />
<br />
'''Custom input method'''<br />
<br />
I wrote my own input method:<br />
<br />
github: https://github.com/roelvandijk/emacs-haskell-unicode-input-method<br />
checkout: git clone git://github.com/roelvandijk/emacs-haskell-unicode-input-method.git<br />
<br />
To automically load in haskell-mode put the following code in your .emacs file:<br />
(require 'haskell-unicode-input-method)<br />
(add-hook 'haskell-mode-hook <br />
(lambda () (set-input-method "haskell-unicode")))<br />
<br />
Make sure the directory containing the .elisp file is in your load-path, for example:<br />
(add-to-list 'load-path "~/.elisp/emacs-haskell-unicode-input-method")<br />
<br />
To manually enable use <tt>M-x set-input-method</tt> or <tt>C-x RET C-\</tt> with <tt>haskell-unicode</tt>. Note that the elisp file must be evaluated for this to work.<br />
<br />
Now you can simply type <tt>-></tt> and it is immediately replaced with &rarr;. Use <tt>C-\</tt> to toggle the input method. To see a table of all key sequences use <tt>M-x describe-input-method haskell-unicode</tt>. A sequence like <= is ambiguous and can mean either <tt>&lArr;</tt> or <tt>&le;</tt>. Typing it presents you with a choice. Type 1 or 2 to select an option or keep typing to use the default option.<br />
<br />
If you don't like the highlighting of partially matching tokens you can turn it off:<br />
<br />
(setq input-method-highlight-flag nil)<br />
<br />
'''Abbrev mode'''<br />
<br />
The [http://www.gnu.org/software/emacs/manual/html_node/emacs/Abbrevs.html Abbrev mode] is not suitable since it only deals with ''words'', not ''operators''.<br />
<br />
'''Agda'''<br />
<br />
Use Agda's [http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Docs.UnicodeInput input method].<br />
<br />
=== Vim ===<br />
<br />
(''real Vim users might want to expand this section'')<br />
<br />
'''Direct'''<br />
<br />
* Decimal value: type '''C-Vnnn''' where 0 &le; nnn &le; 255.<br />
* Octal value: type '''C-VOnnn''' or '''C-Vonnn''' where 0 &le; nnn &le; 377.<br />
* Hex value: type '''C-VXnn''' or '''C-Vxnn''' where 0 &le; nn &le; FF.<br />
* Hex value for BMP codepoints: type '''C-Vunnnn''' where 0 &le; nnnn &le; FFFF.<br />
* Hex value for any codepoint: type '''C-VUnnnnnnnn''' where 0 &le; nnnnnnnn &le; FFFFFFFF.<br />
<br />
'''Automatic Unicode Transformation'''<br />
<br />
Furthermore, there is a Haskell file type plugin called [https://github.com/frerich/unicode-haskell unicode-haskell] which automatically transforms ASCII character sequences (e.g. -> and many others) to Unicode when loading Haskell source code - and the data is converted back when saving. That way, the source code remains plain ASCII on disk but uses nice Unicode characters in vim/gvim. Furthermore, the plugin will automatically replace ASCII sequences with their Unicode equivalents as you type.<br />
<br />
=== SciTE ===<br />
<br />
See [[Tips_for_using_SciTE_with_Haskell]]<br />
<br />
=== System wide ===<br />
<br />
'''m17n input methods'''<br />
<br />
A set of input methods has been written by Urs Holzer for the [http://www.m17n.org m17n] library. The main goal of Urs is to build input methods for mathematical characters. However, most of the symbols used in the *-unicode-symbols packages can be written using Urs's methods. More information is available at [http://www.andonyar.com/rec/2008-03/mathinput/ Input Methods for Mathematics] page. For most Linux distributions, just download a [http://www.andonyar.com/rec/2008-03/mathinput/methods.tar.gz tarball], extract *.mim files to /usr/share/m17n and enable iBus for input methods.<br />
<br />
== Fonts ==<br />
<br />
The following free fonts have good Unicode coverage:<br />
<br />
* [http://www.gnome.org/fonts/ Bitstream Vera Font Family]<br />
* [http://dejavu-fonts.org/wiki/Main_Page DejaVu Font Family]<br />
* [http://linuxlibertine.sourceforge.net/ Linux Libertine Font]<br />
* [https://www.redhat.com/promo/fonts/ RedHat Liberation Fonts]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Tips_for_using_SciTE_with_Haskell&diff=42240Tips for using SciTE with Haskell2011-09-30T16:11:25Z<p>Amy de B: </p>
<hr />
<div>Here are some useful abbreviations, if you like using the Unicode symbols. Create a file named abbrev.properties in your home directory, and paste in the code below. (If you already have a file named abbrev.properties, add the code below to that file.)<br />
<br />
<haskell><br />
# 0x2237 PROPORTION<br />
::=∷|<br />
# 0x21D2 RIGHTWARDS DOUBLE ARROW (can't use equals in an abbreviation name)<br />
e>=⇒|<br />
# 0x2200 FOR ALL<br />
forall=∀|<br />
# 0x2192 RIGHTWARDS ARROW<br />
->=→|<br />
# 0x2190 LEFTWARDS ARROW<br />
<-=←|<br />
# 0x2919 LEFTWARDS ARROW-TAIL<br />
-<=↢|<br />
# 0x291A RIGHTWARDS ARROW-TAIL<br />
>-=↣|<br />
# 0x291B LEFTWARDS DOUBLE ARROW-TAIL<br />
-<<=⤛|<br />
# 0x291C RIGHTWARDS DOUBLE ARROW-TAIL<br />
>>-=⤜|<br />
# 0x2605 BLACK STAR<br />
*=★|<br />
</haskell><br />
<br />
<br />
Afterward, you can use the following shortcuts:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Type this, then Ctrl+B...<br />
! ...to get<br />
|-<br />
| :: <br />
| ∷<br />
|-<br />
| e> <br />
| ⇒<br />
|-<br />
| forall <br />
| ∀<br />
|-<br />
| -> <br />
| →<br />
|-<br />
| <- <br />
| ←<br />
|-<br />
| -< <br />
| ↢<br />
|-<br />
| >- <br />
| ↣<br />
|-<br />
| -<< <br />
| ⤛<br />
|-<br />
| >>- <br />
| ⤜<br />
|-<br />
| * <br />
| ★<br />
|}</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Editors&diff=42239Editors2011-09-30T16:06:06Z<p>Amy de B: /* Syntax highlighting and formatting support */</p>
<hr />
<div>[[Category:Tools]]<br />
<br />
This page lists Haskell-aware editors. It is currently broken into IDEs (editing plus project management) and customizations for Haskell syntax highlighting and formatting support in text editors. [[User:DavorC|DavorC]] 03:04, 17 February 2006 (UTC)<br />
<br />
== Integrated Development Environments ==<br />
<br />
* [http://eclipsefp.sourceforge.net/ Eclipse]<br />
* Visual Haskell<br />
* [[Leksah]]<br />
* KDevelop<br />
* [[hIDE]]<br />
* [http://www.cs.kent.ac.uk/projects/heat/ HEAT:] An Interactive Development Environment for Learning & Teaching Haskell<br />
<br />
== Syntax highlighting and formatting support ==<br />
<br />
Multi-platform<br />
* [http://www.gnu.org/software/emacs/ Emacs]<br />
** [[Haskell mode for Emacs |Haskell mode]]<br />
** Integration with [[Hugs]]<br />
* [http://www.vim.org/ Vim]<br />
** [http://www.vim.org/scripts/script.php?script_id=2356 Superior Haskell Interaction Mode]<br />
* [http://www.nedit.org/ Nedit]<br />
* [http://www.jedsoft.org/jed/ Jed]<br />
Linux<br />
* [http://kate-editor.org/kate Kate (KDE)]<br />
* [http://www.scintilla.org/SciTE.html SciTE] (Also see these [[Tips for using SciTE with Haskell|tips]])<br />
Windows<br />
* [http://www.sublimetext.com/ Sublime Text]<br />
* [http://www.textpad.com/ Textpad]<br />
* [http://notepad-plus.sourceforge.net Notepad++]<br />
MacOS X<br />
* [http://www.codingmonkeys.de/subethaedit/ SubEthaEdit]<br />
* [http://macromates.com/ TextMate] has a [http://macromates.com/textmate/manual/bundles#installing_a_bundle Haskell bundle]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Tips_for_using_SciTE_with_Haskell&diff=42238Tips for using SciTE with Haskell2011-09-30T16:03:54Z<p>Amy de B: New page: Here are some useful abbreviations, if you like using the Unicode symbols. Create a file named abbrev.properties in your home directory, and paste in the code below. (If you already have a...</p>
<hr />
<div>Here are some useful abbreviations, if you like using the Unicode symbols. Create a file named abbrev.properties in your home directory, and paste in the code below. (If you already have a file named abbrev.properties, add the code below to that file.)<br />
<br />
<haskell><br />
# 0x2237 PROPORTION<br />
::=∷|<br />
# 0x21D2 RIGHTWARDS DOUBLE ARROW (can't use equals in an abbreviation name)<br />
e>=⇒|<br />
# 0x2200 FOR ALL<br />
forall=∀|<br />
# 0x2192 RIGHTWARDS ARROW<br />
->=→|<br />
# 0x2190 LEFTWARDS ARROW<br />
<-=←|<br />
# 0x2919 LEFTWARDS ARROW-TAIL<br />
-<=↢|<br />
# 0x291A RIGHTWARDS ARROW-TAIL<br />
>-=↣|<br />
# 0x291B LEFTWARDS DOUBLE ARROW-TAIL<br />
-<<=⤛|<br />
# 0x291C RIGHTWARDS DOUBLE ARROW-TAIL<br />
>>-=⤜|<br />
# 0x2605 BLACK STAR<br />
*=★|<br />
</haskell><br />
<br />
<br />
Afterward, you can use the following shortcuts:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Type this, then Ctrl+B...<br />
! ...to get<br />
|-<br />
| row 1, cell 1<br />
| row 1, cell 2<br />
|-<br />
| :: <br />
| ∷<br />
|-<br />
| e> <br />
| ⇒<br />
|-<br />
| forall <br />
| ∀<br />
|-<br />
| -> <br />
| →<br />
|-<br />
| <- <br />
| ←<br />
|-<br />
| -< <br />
| ↢<br />
|-<br />
| >- <br />
| ↣<br />
|-<br />
| -<< <br />
| ⤛<br />
|-<br />
| >>- <br />
| ⤜<br />
|-<br />
| * <br />
| ★<br />
|-<br />
| row 3, cell 1<br />
| row 3, cell 2<br />
|}</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Editors&diff=42237Editors2011-09-30T15:44:48Z<p>Amy de B: /* Syntax highlighting and formatting support */</p>
<hr />
<div>[[Category:Tools]]<br />
<br />
This page lists Haskell-aware editors. It is currently broken into IDEs (editing plus project management) and customizations for Haskell syntax highlighting and formatting support in text editors. [[User:DavorC|DavorC]] 03:04, 17 February 2006 (UTC)<br />
<br />
== Integrated Development Environments ==<br />
<br />
* [http://eclipsefp.sourceforge.net/ Eclipse]<br />
* Visual Haskell<br />
* [[Leksah]]<br />
* KDevelop<br />
* [[hIDE]]<br />
* [http://www.cs.kent.ac.uk/projects/heat/ HEAT:] An Interactive Development Environment for Learning & Teaching Haskell<br />
<br />
== Syntax highlighting and formatting support ==<br />
<br />
Multi-platform<br />
* [http://www.gnu.org/software/emacs/ Emacs]<br />
** [[Haskell mode for Emacs |Haskell mode]]<br />
** Integration with [[Hugs]]<br />
* [http://www.vim.org/ Vim]<br />
** [http://www.vim.org/scripts/script.php?script_id=2356 Superior Haskell Interaction Mode]<br />
* [http://www.nedit.org/ Nedit]<br />
* [http://www.jedsoft.org/jed/ Jed]<br />
Linux<br />
* [http://kate-editor.org/kate Kate (KDE)]<br />
* [http://www.scintilla.org/SciTE.html SciTE]<br />
Windows<br />
* [http://www.sublimetext.com/ Sublime Text]<br />
* [http://www.textpad.com/ Textpad]<br />
* [http://notepad-plus.sourceforge.net Notepad++]<br />
MacOS X<br />
* [http://www.codingmonkeys.de/subethaedit/ SubEthaEdit]<br />
* [http://macromates.com/ TextMate] has a [http://macromates.com/textmate/manual/bundles#installing_a_bundle Haskell bundle]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Gentoo/HaskellPlatform&diff=32669Gentoo/HaskellPlatform2009-12-20T17:04:30Z<p>Amy de B: Mentioned Cabal in the list of things pulled in by emerge</p>
<hr />
<div>Gentoo supports the Haskell Platform!<br />
<br />
==Unmasking GHC 6.10.4 and the Haskell Platform==<br />
<br />
Currently (2009-08-02) GHC 6.10.4 and a few libraries are hard masked, meaning you will have to p.unmask yourself before installing. This is because we're still updating the portage packages to get full GHC 6.10.4 support.<br />
<br />
<code><br />
echo dev-lang/ghc >> /etc/portage/package.unmask<br />
echo dev-haskell/parallel >> /etc/portage/package.unmask<br />
echo dev-haskell/haddock >> /etc/portage/package.unmask<br />
echo app-admin/haskell-updater >> /etc/portage/package.unmask<br />
</code><br />
<br />
As the haskell-platform depends on this recent GHC version, you'll need to unmask it too;<br />
<br />
<code><br />
echo dev-haskell/haskell-platform >> /etc/portage/package.unmask<br />
</code><br />
<br />
Don't forget that these packages are also ~keyworded.<br />
<br />
==Install==<br />
<br />
Now, to install, run:<br />
<br />
<code><br />
emerge haskell-platform<br />
</code><br />
<br />
This will pull the GHC compiler, Cabal, and all the libraries included in HP. If you want haddock documentation, set your <code>USE="doc"</code>. If you also want profiling libraries, set <code>USE="profile"</code>.<br />
<br />
==Feedback==<br />
<br />
Got any feedback for the packages above? Let us know!<br />
<br />
You'll find us in <code>#gentoo-haskell @ freenode</code>, or send your comments to [mailto:haskell@gentoo.org haskell@gentoo.org].</div>Amy de Bhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=32659How to write a Haskell program2009-12-19T21:49:39Z<p>Amy de B: Added an example of how to use HLint</p>
<hr />
<div>A guide to creating a new Haskell project or program.<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://darcs.net Darcs] unless you have a specific reason not to.<br />
It's a lightweight distributed revision control system (and it's written in Haskell). Darcs has massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers darcs is probably best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://git-scm.com/ git] and [http://github.com/ github] are also becoming popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal User's Guide].<br />
<br />
You probably also want to use [http://haskell.org/cabal/download.html cabal-install] as a front-end for the Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from and uploading them to Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the latest version of Haddock.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://www.md.chalmers.se/~rjmh/QuickCheck/ QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. <br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/01/simple-unit-testing-in-haskell/ Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
The new tool [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkcabal mkcabal] automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in darcs ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 3 && < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== (Optional) Improve your code: HLint ===<br />
<br />
[[HLint]] can be a valuable tool for improving your coding style, particularly if you're new to Haskell. Let's run it now.<br />
<br />
<code><br />
$ hlint .<br />
./Haq.hs:11:1: Warning: Eta reduce<br />
Found:<br />
haqify s = "Haq! " ++ s<br />
Why not:<br />
haqify = ("Haq! " ++)<br />
</code><br />
<br />
The existing code will work, but let's follow that suggestion. Open Haq.hs in your favourite editor and change the line:<br />
<br />
<haskell><br />
where haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
to:<br />
<br />
<haskell><br />
where haqify = ("Haq! " ++)<br />
</haskell><br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
==== QuickCheck v1 ====<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
==== QuickCheck v2 ====<br />
<br />
If you're using version 2 of QuickCheck, the code in the previous section needs some minor modifications:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", quickCheck prop_reversereverse)<br />
,("drop.haq/id", quickCheck prop_haq)]<br />
</haskell><br />
<br />
To run the test:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : +++ OK, passed 100 tests.<br />
drop.haq/id : +++ OK, passed 100 tests.<br />
</code><br />
<br />
Success!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base >= 3 && < 5<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done! You can use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal documentation].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal install mkcabal<br />
<br />
Usage is:<br />
<br />
<code><br />
$ mkcabal<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created Setup.lhs and haq.cabal<br />
$ ls<br />
Haq.hs LICENSE Setup.lhs _darcs dist haq.cabal<br />
</code><br />
<br />
which will fill out some stub Cabal files for the project 'haq'. <br />
<br />
To create an entirely new project tree:<br />
<br />
<code><br />
$ mkcabal --init-project<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created new project directory: haq<br />
$ cd haq<br />
$ ls<br />
Haq.hs LICENSE README Setup.lhs haq.cabal<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Amy de Bhttps://wiki.haskell.org/index.php?title=Talk:Haskell&diff=32657Talk:Haskell2009-12-19T21:17:30Z<p>Amy de B: </p>
<hr />
<div>== "Search" vs "search" vs "search" ==<br />
<br />
The front page has 3 search boxes:<br />
* at the top with the buttons "Go" and "Search"<br />
* the third link on the left called "Search"<br />
* the next link below "Search haskell.org"<br />
<br />
What is the difference? Is this really necessary?<br />
--[[User:Lenny222|Lenny222]] 10:58, 24 April 2009 (UTC)<br />
<br />
== "Libraries" vs "Packages" ==<br />
<br />
The front pages says "Find a library" and links to Hackages which lists "packages". To reduce confusion, i think we should settle to the usage of only "packages". Opinions?<br />
<br />
--[[User:Lenny222|Lenny222]] 12:09, 24 February 2009 (UTC)<br />
<br />
<br />
== Usability ==<br />
<br />
[[User:Lenny222/Haskell|This is a sketch]] implementing my ideas below.<br />
<br />
The Haskell Wiki includes a bunch of useful information.<br />
I think we can still improve on how easy these information are available.<br />
<br />
The current front page is too packed for my taste. The side bar for example contains over 50 links. Compare this with the Python and Ruby homepages with around 10 major links. Regarding the [http://www.smashingmagazine.com/2007/10/09/30-usability-issues-to-be-aware-of/ rule of 7] we should reduce the information we present on the front page.<br />
<br />
Who are our visitors and what do they want?<br />
<br />
* Beginners. People who have no clue what Haskell is want to find answers to the following questions<br />
** What is Haskell?<br />
** How does Haskell look and "feel"?<br />
** Why should i care?<br />
** Who else i using Haskell?<br />
** How do i get started?<br />
* Intermediates. People who are getting an idea what Haskell is but want to find out more about it, want to find answers to the following questions<br />
** Where can i read some tutorials?<br />
** Where can i read the API documentation?<br />
** What is going on in the Haskell comunity?<br />
* Experts. People who know a lot about Haskell, but come back here, because they want to find answers to the following questions<br />
** What is going on in the Haskell comunity?<br />
** Where can i read about Haskell's future?<br />
<br />
I propose the following grouping:<br />
<br />
* About Haskell<br />
** What is Haskell?<br />
** How does Haskell feels like?<br />
** Haskell success stories<br />
** Getting Started<br />
*** Installation guide<br />
*** First steps guides<br />
* Download<br />
* Documentation<br />
** Tutorials<br />
** How to install packages via Cabal/Hackages<br />
** API documentation<br />
*** GHC static pages<br />
*** Hoogle<br />
** Community<br />
*** Blogs<br />
*** Events<br />
*** Projects<br />
<br />
Is there any Webmaster comitee or mailinglist to discuss this?<br />
<br />
<br />
=== Usability: Developer Tools ===<br />
<br />
One of the things a beginner wants to find out quickly is: What tools are available for the developer? The front page does have a link to <br />
[[http://haskell.org/haskellwiki/Applications_and_libraries/Program_development Applications_and_libraries/Program_development]], which has exactly the kind of info I was looking for. Unfortunately, I overlooked it the first few times because I was scanning for words like "tools" or "editors" or "IDEs". Maybe it would be a good idea to simply rename the article to "Developer Tools". I think that's a better description of the content, and it would make it easier for beginners to find the info.<br />
<br />
--[[User:Amy de B|Amy de B]] 21:17, 19 December 2009 (UTC)<br />
<br />
== New book on the market,especially for Romania and Moldova ==<br />
<br />
[[Image:Coperta5.jpg|center|Practica interpretarii monadice]]<br />
<br />
A new book (by Dan Popa from Bacau State Univ.) called "Practice of monads interpreters" - title translated by the editor - (orig. Practica Interpretarii monadice) is on the market. It is offered by the MatrixRom Pub. House http://www.matrixrom.ro . Suport: Paper Price: 20 lei (less then 7 euros, grab it !!). Language: romanian (yet.)<br />
<br />
<br />
The Ro/Page of the book is here: http://www.haskell.org/haskellwiki/Practica_interpretarii_monadice<br />
<br />
Other books by MatrixRom are here: http://www.matrixrom.ro/english/publishing/domains/computer_science.php?id=901#901<br />
<br />
May I add it on the Headline section or somewhere else on the front page, this week ? Or should I make an English page for this (long) text ?<br />
<br />
Thanx<br />
Dan<br />
<br />
<br />
== Question Concerning Who's using Haskell? ==<br />
<br />
Haskell is used at Bacau State University (www.ub.ro) by Lect. Drd. Dan Popa as a tool for DSL (ak. domain small languges) building. Also, DSLs like [[Rodin]] are used as tools for teaching "Fundamentals of Programming Languages".<br />
<br />
Should I add this note on the main page ? Can anybody check it (ex. spelling) and post it.<br />
Thx<br />
<br />
Dan Popa<br />
<br />
Ro/Haskell <br />
<br />
If no remarks will be made during this week I will consider such news as acceptable and accepted the first page of www.haskell.org . With no votes against them.<br />
<br />
Thax again<br />
<br />
Dan<br />
<br />
== Search Box doesn't find short words == <br />
<br />
Just leaving a note here to say that the Search box and button at the top of the page now works properly except for words of three characters or less. These are not indexed and will give no results. (See [http://www.haskell.org/pipermail/haskell-cafe/2008-February/039579.html Haskell-Cafe post by Mads LindstrÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂøm] for possible administrator technical solution and related threads.) --[[User:Rk|Rk]]<br />
<br />
== EduSoft.ro URL ==<br />
<br />
THE EduSoft URL is: www.edusoft.ro NOT edusoft.com. <br />
You can see it in the Ro/Haskell page ! See the details.<br />
Thank you for other (wellcome) corrections.<br />
<br />
:Calm down, I've fixed it. Naturally I googled it and assumed the parent company was the one to link to. --[[User:Gwern|Gwern]] 23:04, 13 December 2007 (UTC)<br />
<br />
Well done.<br />
<br />
== Logo and design ==<br />
<br />
This is currently just made to look like http://haskell.org/. I expect we will want to change it later. &mdash;[[User:Ashley Y|Ashley Y]] 21:58, 9 January 2006 (EST)<br />
<br />
IMO the logo and design looks very amateurish. Are there no Haskell programmers with some experience in graphic design? Or maybe someone who knows someone?<br />
--[[User:SebastianSylvan|SebastianSylvan]] 13:06, 11 January 2006 (EST)<br />
<br />
:The logo seems to be well established as the "Haskell" logo. &mdash;[[User:Ashley Y|Ashley Y]] 14:42, 11 January 2006 (EST)<br />
<br />
::That doesn't change anything. In fact, it makes it worse! Appearances matter, if someone who doesn't know Haskell comes here, sees an amateurish web and logo design, they may not consider Haskell a "real" language, but rather an amateurish effort not suited for real work. In fact I'd prefer an approach similar to e.g. the ruby web site (no logo at all, rather than an amateurish logo). --[[User:SebastianSylvan|SebastianSylvan]] 03:49, 12 January 2006 (EST)<br />
<br />
: I should clarify that the "Haskell" headline logo is what irks me the most. The lambda-logo thing isn't as bad, although it suffers from many of the same problems ("every-effect-in-photoshop-syndrome"). I'd like it more if it was just a two color logo (and not necessarily green and purple) without all those highlights and bevels.--[[User:SebastianSylvan|SebastianSylvan]] 04:11, 12 January 2006 (EST)<br />
<br />
::You could raise the issue on the mailing list. The round logo at least is used on other haskell sites. &mdash;[[User:Ashley Y|Ashley Y]] 21:24, 31 January 2006 (UTC)<br />
<br />
Is there some way to suppress the wiki page title? - at the moment the page says 'Haskell' in small letters right above a huge logo also saying 'Haskell'. It looks pretty stupid. -- [[User:MikeDodds|MikeDodds]] 15:01, 20 February 2006 (UTC)<br />
<br />
The round logo at the left (which I agree is pretty garish) still takes a line by itself, leaving lots of dead white space for only a centered page title to follow it. I suggest leaving the logo at the top left, then moving the page title to the top-right. This will fix the aforementioned silliness with the home page title as well as clear up a little vertical real estate. -- [[User:Chuck Adams|Chuck Adams]] 17:24, 22 February 2006 (UTC)<br />
<br />
:There is a way, but we'd need somebody with admin rights on the wiki to edit the relevant skin file: http://article.gmane.org/gmane.org.wikimedia.mediawiki/1521<br />
: -- [[User:EricKow|kowey]] 13:45, 17 February 2007 (UTC)<br />
<br />
== Revamp ==<br />
<br />
I'm going to change this page to better reflect the existing content of the wiki, rather than the content of haskell.org. &mdash;[[User:Ashley Y|Ashley Y]] 05:43, 14 January 2006 (UTC)<br />
<br />
We should probably clean up some of the clutter. I'd like to transfer everything more or less as is and the let the site go to the wiki before coming back to clean up. I'm planning to leave the old web pages for things like the history of Haskell alone at the moment.<br />
--[[User:John Peterson|John Peterson]] 17:36, 24 January 2006 (UTC)<br />
<br />
Maybe the "learning" section should be improved? As it is none of the links under it are extremely useful. Maybe they could be concatenated and split up into "tutorials" for mere mortals, and papers which probably aren't as useful to the newbie? Also, an idea is to redesign to have the news section up in front and visible. The more important items in HWN etc. could be put here (significant new libraries etc). After all, most people are very web-centric these days so using the Haskell.org site as a general announcement page is probably a good idea if it doesn't get too cluttered.<br />
<br />
In fact, I already have a 'significant news' page generated from the HWN<br />
archives, [http://www.cse.unsw.edu.au/~dons/code/hwn/announce.html here].<br />
If this headlines of this kind of content is what we'd like to appear in<br />
a news bar on the page somewhere, just make a place, and I'll update it<br />
as the HWN is published each week. -- Don Stewart<br />
<br />
: Please do! I think significant news (about new libraries, for instance) should be on the front page. If for no other reason than letting casual browsers know that the community is active. Just add titles (with dates) on each news entry on the existing news page. --[[User:SebastianSylvan|SebastianSylvan]] 15:33, 13 March 2006 (UTC)<br />
<br />
== Plan : whitespace issues ==<br />
<br />
I've made the "Haskell : A purely functional language" smaller now, so<br />
its more inline with with python.org, and perl.org logos. My model is<br />
[http://python.org/ python.org], I think our img header should be only a<br />
bit bigger than that.<br />
<br />
The problem still remains that there is too much empty whitespace at the<br />
top of the page, before the real content. Ideally I'd like:<br />
<br />
* 1. a smaller circular logo, about 80% of the current size<br />
* 2. align the circle and text logos.<br />
* 3. remove the "Haskell" wiki title from the page<br />
<br />
So we just need to work out how to do steps 2 and 3.<br />
<br />
Opinions? -- [[User:DonStewart]] Wed Apr 12 16:23:47 EST 2006<br />
<br />
There doesn't seem to be an easy way to remove the title on a particular page. I asked about it on the Mediawiki irc channel, and I found this [http://mail.wikipedia.org/pipermail/mediawiki-l/2005-June/005419.html thread] on the Mediawiki-l mailing list. -- [[User:JohnHamilton|JohnHamilton]] 19:07, 14 April 2006 (UTC)<br />
<br />
== Search with Hoogle box? ==<br />
Lots of websites have a search with google box, maybe a search with hoogle box on the front page (small and discrete) would be appropriate? --[[User:NeilMitchell|Neil Mitchell]] 13:42, 20 February 2006 (UTC)<br />
<br />
: That might be a good idea - the only thing that you'd have to be careful about is that it needs to be clear that Hoogle isn't a web search engine. You could easily confuse people, especially given the name - [[User:MikeDodds|MikeDodds]] 17:43, 27 February 2006 (UTC)<br />
<br />
== Well-formedness / validity ==<br />
Not sure where to put this...<br />
<br />
Currently every Haskell-wiki page is [http://validator.w3.org/check?verbose=1&uri=http%3A%2F%2Fwww.haskell.org%2Fhaskellwiki%2FHaskell invalid XHTML 1.0 Transitional] and in fact not even well-formed XML (as I mention on my [http://en.wikipedia.org/wiki/User:Isaac_Dupree Wikipedia user page], which I'll update if this is fixed!). Most browsers don't mind because it's served as text/html, which it needs to stay for Internet Explorer... Anyway. Whoever controls the header at the top of the haskell-wiki pages:<br />
*Assuming the (X)HTML in the header can be modified...<br />
*The &lt;form> in the header (the search box) [http://www.w3.org/TR/html401/interact/forms.html is a block-level element]. However it occurs inside a &lt;p> element that contains<br />
:Haskell | Wiki community | Recent changes<br />
:Random page | Upload file | Special pages<br />
:(search box)<br />
<br />
:This is not even very much like a paragraph. Turning that &lt;p>...&lt;/p> into a &lt;div>...&lt;/div> would fix this.<br />
*The Haskell logo in the top left corner is implemented with &lt;img ...>. Firstly, this is not well-formed! It should end like &lt;img ... />. Secondly, it needs an alt="something" attribute. Since this logo also functions as a link, the alt text should be non-empty. I suggest alt="ÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂû" (replacing the logo with a lambda character, which is utf-8 as per the character encoding, or perhaps the equivalent alt="&amp;#955;")<br />
<br />
Testing these changes in my own copy, in Internet Explorer 6, Firefox 2 and Konqueror 3.5.5, I observed no ill effects (and a nice lambda effect when the image was unavailable in firefox, konqueror and some text-only browser). And the W3C HTML validator was happy and the CSS validator (which relies on the XML correctness) worked.<br />
<br />
Incidentally, http://haskell.org/ghc/ is valid, <br />
http://haskell.org/hugs/ isn't, http://haskell.org/gtk2hs/ mostly is... but, never mind that ;) (i.e. I won't pursue those)<br />
<br />
Hoping this is an easy fix ÃÂÃÂÃÂÃÂÃÂÃÂÃÂâÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂ[[User:Isaac Dupree|Isaac Dupree]] 19:12, 19 February 2007 (UTC)<br />
:Now HaskellWiki is well-formed and valid ÃÂÃÂÃÂÃÂÃÂÃÂÃÂâÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂ[[User:Isaac Dupree|Isaac Dupree]] 14:02, 6 August 2007 (UTC)<br />
<br />
::I can't guarantee that, it's quite possible that some page's wiki content will translate to bad XHTML. &mdash;[[User:Ashley Y|Ashley Y]] 01:06, 7 August 2007 (UTC)</div>Amy de Bhttps://wiki.haskell.org/index.php?title=How_to_write_a_Haskell_program&diff=32651How to write a Haskell program2009-12-19T20:50:00Z<p>Amy de B: Added code sample that works with QuickCheck2</p>
<hr />
<div>A guide to creating a new Haskell project or program.<br />
<br />
== Recommended tools ==<br />
<br />
Almost all new Haskell projects use the following tools. Each is<br />
intrinsically useful, but using a set of common tools also helps<br />
everyone by increasing productivity, and you're more likely to get<br />
patches.<br />
<br />
=== Revision control ===<br />
<br />
Use [http://darcs.net Darcs] unless you have a specific reason not to.<br />
It's a lightweight distributed revision control system (and it's written in Haskell). Darcs has massive market share in the Haskell world, if you want to encourage contributions from other Haskell hackers darcs is probably best. Darcs hosting is available on [http://code.haskell.org code.haskell.org] and [http://patch-tag.com patch-tag]. [http://git-scm.com/ git] and [http://github.com/ github] are also becoming popular.<br />
<br />
=== Build system ===<br />
<br />
[[Image:Cabal-With-Text-small.png|frame|Built with Cabal]]<br />
<br />
Use [http://haskell.org/cabal/ Cabal].<br />
You should read at least the start of section 2 of the [http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal User's Guide].<br />
<br />
You probably also want to use [http://haskell.org/cabal/download.html cabal-install] as a front-end for the Cabal library. Cabal-install provides commands not only for building libraries but also for installing them from and uploading them to Hackage. As a bonus, for almost all programs, it's faster than using Setup.hs scripts directly, since no time is wasted compiling the scripts. (This does not apply for programs that use custom Setup.hs scripts, since those need to be compiled even when using cabal-install.)<br />
<br />
=== Documentation ===<br />
<br />
For libraries, use [http://haskell.org/haddock/ Haddock]. We recommend<br />
using the latest version of Haddock.<br />
<br />
=== Testing ===<br />
<br />
You can use [http://www.md.chalmers.se/~rjmh/QuickCheck/ QuickCheck] or [http://www.mail-archive.com/haskell@haskell.org/msg19215.html SmallCheck] to test pure code. To test impure code, use [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HUnit HUnit]. <br />
<br />
To get started, try [[Introduction to QuickCheck]]. For a slightly more advanced introduction, [http://blog.codersbase.com/2006/09/01/simple-unit-testing-in-haskell/ Simple Unit Testing in Haskell] is a blog article about creating a testing framework for QuickCheck using some Template Haskell. For HUnit, see [[HUnit 1.0 User's Guide]]<br />
<br />
=== Distribution ===<br />
<br />
The standard mechanism for distributing Haskell libraries and<br />
applications is [http://hackage.haskell.org/packages/hackage.html Hackage]. Hackage can<br />
host your cabalised tarball releases, and link to any library<br />
dependencies your code has.<br />
<br />
== Structure of a simple project ==<br />
<br />
The basic structure of a new Haskell project can be adopted from<br />
[http://semantic.org/hnop/ HNop], the minimal Haskell project. It<br />
consists of the following files, for the mythical project "haq".<br />
<br />
* Haq.hs -- the main haskell source file<br />
* haq.cabal -- the cabal build description<br />
* Setup.hs -- build script itself<br />
* _darcs -- revision control<br />
* README -- info<br />
* LICENSE -- license<br />
<br />
Of course, you can elaborate on this, with subdirectories and multiple<br />
modules. See [[Structure of a Haskell project]] for an example of a larger project's directory structure.<br />
<br />
Here is a transcript that shows how you'd create a minimal darcs and cabalised<br />
Haskell project for the cool new Haskell program "haq", build it,<br />
install it and release.<br />
<br />
The new tool [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkcabal mkcabal] automates all this for you, but you should<br />
understand all the parts even so. <br />
<br />
We will now walk through the creation of the infrastructure for a simple<br />
Haskell executable. Advice for libraries follows after.<br />
<br />
=== Create a directory ===<br />
<br />
Create somewhere for the source:<br />
<br />
<code><br />
$ mkdir haq<br />
$ cd haq<br />
</code><br />
<br />
=== Write some Haskell source ===<br />
<br />
Write your program:<br />
<br />
<haskell><br />
$ cat > Haq.hs<br />
--<br />
-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
--<br />
import System.Environment<br />
<br />
-- | 'main' runs the main program<br />
main :: IO ()<br />
main = getArgs >>= print . haqify . head<br />
<br />
haqify s = "Haq! " ++ s<br />
</haskell><br />
<br />
=== Stick it in darcs ===<br />
<br />
Place the source under revision control (you may need to enter your e-mail address first, to identify you as maintainer of this source):<br />
<br />
<code><br />
$ darcs init<br />
$ darcs add Haq.hs <br />
$ darcs record<br />
addfile ./Haq.hs<br />
Shall I record this change? (1/?) [ynWsfqadjkc], or ? for help: y<br />
hunk ./Haq.hs 1<br />
+--<br />
+-- Copyright (c) 2006 Don Stewart - http://www.cse.unsw.edu.au/~dons/<br />
+-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)<br />
+--<br />
+import System.Environment<br />
+<br />
+-- | 'main' runs the main program<br />
+main :: IO ()<br />
+main = getArgs >>= print . haqify . head<br />
+<br />
+haqify s = "Haq! " ++ s<br />
Shall I record this change? (2/?) [ynWsfqadjkc], or ? for help: y<br />
What is the patch name? Import haq source<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Import haq source'<br />
</code><br />
<br />
And we can see that darcs is now running the show:<br />
<br />
<code><br />
$ ls<br />
Haq.hs _darcs<br />
</code><br />
<br />
=== Add a build system ===<br />
<br />
Create a .cabal file describing how to build your project:<br />
<br />
<code><br />
$ cat > haq.cabal<br />
Name: haq<br />
Version: 0.0<br />
Description: Super cool mega lambdas<br />
License: GPL<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Executable haq<br />
Main-is: Haq.hs<br />
Build-Depends: base >= 3 && < 5<br />
</code><br />
<br />
(If your package uses other packages, e.g. <tt>haskell98</tt>, you'll need to add them to the <tt>Build-Depends:</tt> field as a comma separated list.)<br />
Add a <tt>Setup.hs</tt> that will actually do the building:<br />
<br />
<haskell><br />
$ cat > Setup.hs<br />
import Distribution.Simple<br />
main = defaultMain<br />
</haskell><br />
Cabal allows either <tt>Setup.hs</tt> or <tt>Setup.lhs</tt>.<br />
<br />
Now would also be a good time to add a LICENSE file and a README file. Examples are in the tarball for HNop.<br />
<br />
Record your changes:<br />
<br />
<code><br />
$ darcs add haq.cabal Setup.hs LICENSE README<br />
$ darcs record --all<br />
What is the patch name? Add a build system<br />
Do you want to add a long comment? [yn]n<br />
Finished recording patch 'Add a build system'<br />
</code><br />
<br />
=== Build your project ===<br />
<br />
Now build it! There are two methods of accessing Cabal functionality: through your Setup.hs script or through cabal-install. In most cases, cabal-install is now the preferred method.<br />
<br />
Building using cabal-install:<br />
<br />
<code><br />
$ cabal install --prefix=$HOME --user<br />
</code><br />
<br />
Building using the traditional Setup.hs method:<br />
<br />
<code><br />
$ runhaskell Setup configure --prefix=$HOME --user<br />
$ runhaskell Setup build<br />
$ runhaskell Setup install<br />
</code><br />
<br />
This will install your newly minted haq program in $HOME/bin.<br />
<br />
=== Run it ===<br />
<br />
And now you can run your cool project:<br />
<code><br />
$ haq me<br />
"Haq! me"<br />
</code><br />
<br />
You can also run it in-place, even if you skip the install phase:<br />
<code><br />
$ dist/build/haq/haq you<br />
"Haq! you"<br />
</code><br />
<br />
=== Build some haddock documentation ===<br />
<br />
Generate some API documentation into dist/doc/*<br />
<br />
Using cabal install:<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
Traditional method:<br />
<code><br />
$ runhaskell Setup haddock<br />
</code><br />
<br />
which generates files in dist/doc/ including:<br />
<br />
<code><br />
$ w3m -dump dist/doc/html/haq/Main.html<br />
haq Contents Index<br />
Main<br />
<br />
Synopsis<br />
main :: IO ()<br />
<br />
Documentation<br />
<br />
main :: IO ()<br />
main runs the main program<br />
<br />
Produced by Haddock version 0.7<br />
</code><br />
<br />
No output? Make sure you have actually installed haddock. It is a separate program, not something that comes with Cabal. Note that the stylized comment in the source gets picked up by Haddock.<br />
<br />
=== Add some automated testing: QuickCheck ===<br />
<br />
==== QuickCheck v1 ====<br />
<br />
We'll use QuickCheck to specify a simple property of our Haq.hs code. Create a tests module, Tests.hs, with some QuickCheck boilerplate:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
instance Arbitrary Char where<br />
arbitrary = choose ('\0', '\128')<br />
coarbitrary c = variant (ord c `rem` 4)<br />
</haskell><br />
<br />
Now let's write a simple property:<br />
<br />
<haskell><br />
$ cat >> Tests.hs <br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- and add this to the tests list<br />
tests = [("reverse.reverse/id", test prop_reversereverse)]<br />
</haskell><br />
<br />
We can now run this test, and have QuickCheck generate the test data:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
</code><br />
<br />
Let's add a test for the 'haqify' function:<br />
<br />
<haskell><br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", test prop_reversereverse)<br />
,("drop.haq/id", test prop_haq)]<br />
</haskell><br />
<br />
and let's test that:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
</code><br />
<br />
Great!<br />
<br />
==== QuickCheck v2 ====<br />
<br />
If you're using version 2 of QuickCheck, the code in the previous section needs some minor modifications:<br />
<br />
<haskell><br />
$ cat > Tests.hs<br />
import Char<br />
import List<br />
import Test.QuickCheck<br />
import Text.Printf<br />
<br />
main = mapM_ (\(s,a) -> printf "%-25s: " s >> a) tests<br />
<br />
-- reversing twice a finite list, is the same as identity<br />
prop_reversereverse s = (reverse . reverse) s == id s<br />
where _ = s :: [Int]<br />
<br />
-- Dropping the "Haq! " string is the same as identity<br />
prop_haq s = drop (length "Haq! ") (haqify s) == id s<br />
where haqify s = "Haq! " ++ s<br />
<br />
tests = [("reverse.reverse/id", quickCheck prop_reversereverse)<br />
,("drop.haq/id", quickCheck prop_haq)]<br />
</haskell><br />
<br />
To run the test:<br />
<br />
<code><br />
$ runhaskell Tests.hs<br />
reverse.reverse/id : +++ OK, passed 100 tests.<br />
drop.haq/id : +++ OK, passed 100 tests.<br />
</code><br />
<br />
Success!<br />
<br />
=== Running the test suite from darcs ===<br />
<br />
We can arrange for darcs to run the test suite on every commit:<br />
<br />
<code><br />
$ darcs setpref test "runhaskell Tests.hs"<br />
Changing value of test from '' to 'runhaskell Tests.hs'<br />
</code><br />
<br />
will run the full set of QuickChecks.<br />
If your test requires it, you may need to ensure other things are built too -- for example:<code>darcs setpref test "alex Tokens.x;happy Grammar.y;runhaskell Tests.hs"</code>.<br />
You will encounter that this way a darcs patch is also accepted if a QuickCheck test fails.<br />
You have two choices to [http://www.haskell.org/pipermail/haskell-cafe/2007-October/033834.html work around] this:<br />
* Use <hask>quickCheck'</hask> from the package QuickCheck-2 and call <hask>exitWithFailure</hask> if it return <hask>False</hask>.<br />
* Keep the test program as it is, and implement the failure on the shell level:<br />
: <code>runhaskell Tests.hs | tee test.log && if grep Falsifiable test.log >/dev/null; then exit 1; fi</code><br />
<br />
Let's commit a new patch:<br />
<br />
<code><br />
$ darcs add Tests.hs<br />
$ darcs record --all<br />
What is the patch name? Add testsuite<br />
Do you want to add a long comment? [yn]n<br />
Running test...<br />
reverse.reverse/id : OK, passed 100 tests.<br />
drop.haq/id : OK, passed 100 tests.<br />
Test ran successfully.<br />
Looks like a good patch.<br />
Finished recording patch 'Add testsuite'<br />
</code><br />
<br />
Excellent: now, patches must pass the test suite before they can be committed.<br />
<br />
=== Tag the stable version, create a tarball, and sell it! ===<br />
<br />
Tag the stable version:<br />
<br />
<code><br />
$ darcs tag<br />
What is the version name? 0.0<br />
Finished tagging patch 'TAG 0.0'<br />
</code><br />
<br />
==== Create a tarball ====<br />
You can do this using either Cabal or darcs, or even an explicit <tt>tar</tt> command.<br />
<br />
===== Using Cabal =====<br />
<br />
Since the code is cabalised, we can create a tarball with cabal-install<br />
directly (you can also use <tt>runhaskell Setup.hs sdist</tt>, but you need <tt>tar</tt> on your system [http://thread.gmane.org/gmane.comp.lang.haskell.cafe/60617/focus=60653]):<br />
<br />
<code><br />
$ cabal sdist<br />
Building source dist for haq-0.0...<br />
Source tarball created: dist/haq-0.0.tar.gz<br />
</code><br />
This has the advantage that Cabal will do a bit more checking, and<br />
ensure that the tarball has the structure that HackageDB expects. <br />
Note that it does require the LICENSE file to exist.<br />
It packages up the files needed to build the project; to include other files (such as <tt>Test.hs</tt> in the above example, and our README), we need to add:<br />
<br />
<code><br />
extra-source-files: Tests.hs README<br />
</code><br />
<br />
to the .cabal file to have everything included.<br />
<br />
===== Using darcs =====<br />
<br />
Alternatively, you can use darcs:<br />
<code><br />
$ darcs dist -d haq-0.0<br />
Created dist as haq-0.0.tar.gz<br />
</code><br />
<br />
And you're all set up!<br />
<br />
==== Check that your source package is complete ====<br />
<br />
Just to make sure everything works, try building the source package in some temporary directory:<br />
<code><br />
$ tar xzf haq-0.0.tar.gz<br />
$ cd haq-0.0<br />
$ cabal configure<br />
$ cabal build<br />
</code><br />
and for packages containing libraries,<br />
<code><br />
$ cabal haddock<br />
</code><br />
<br />
==== Upload your package to Hackage ====<br />
<br />
Whichever of the above methods you've used to create your package, you can upload it to the Hackage package collection via a [http://hackage.haskell.org/packages/upload.html web interface].<br />
You may wish to use the package checking interface there first, and fix things it warns about, before uploading your package.<br />
<br />
=== Summary ===<br />
<br />
The following files were created:<br />
<br />
$ ls<br />
Haq.hs Tests.hs dist haq.cabal<br />
Setup.hs _darcs haq-0.0.tar.gz<br />
<br />
== Libraries ==<br />
<br />
The process for creating a Haskell library is almost identical. The differences<br />
are as follows, for the hypothetical "ltree" library:<br />
<br />
=== Hierarchical source ===<br />
<br />
The source should live under a directory path that fits into the<br />
existing [[Hierarchical module names|module layout guide]].<br />
So we would create the following directory structure, for the module<br />
Data.LTree:<br />
<br />
$ mkdir Data<br />
$ cat > Data/LTree.hs <br />
module Data.LTree where<br />
<br />
So our Data.LTree module lives in Data/LTree.hs<br />
<br />
=== The Cabal file ===<br />
<br />
Cabal files for libraries list the publically visible modules, and have<br />
no executable section:<br />
<br />
$ cat > ltree.cabal <br />
Name: ltree<br />
Version: 0.1<br />
Description: Lambda tree implementation<br />
License: BSD3<br />
License-file: LICENSE<br />
Author: Don Stewart<br />
Maintainer: dons@cse.unsw.edu.au<br />
Build-Type: Simple<br />
Cabal-Version: >=1.2<br />
<br />
Library<br />
Build-Depends: base >= 3 && < 5<br />
Exposed-modules: Data.LTree<br />
ghc-options: -Wall<br />
<br />
We can thus build our library:<br />
<br />
$ cabal configure --prefix=$HOME --user<br />
$ cabal build <br />
Preprocessing library ltree-0.1...<br />
Building ltree-0.1...<br />
[1 of 1] Compiling Data.LTree ( Data/LTree.hs, dist/build/Data/LTree.o )<br />
/usr/bin/ar: creating dist/build/libHSltree-0.1.a<br />
<br />
and our library has been created as a object archive. Now install it:<br />
<br />
$ cabal install<br />
Installing: /home/dons/lib/ltree-0.1/ghc-6.6 & /home/dons/bin ltree-0.1...<br />
Registering ltree-0.1...<br />
Reading package info from ".installed-pkg-config" ... done.<br />
Saving old package config file... done.<br />
Writing new package config file... done.<br />
<br />
And we're done! You can use your new library from, for example, ghci:<br />
<br />
$ ghci -package ltree<br />
Prelude> :m + Data.LTree<br />
Prelude Data.LTree> <br />
<br />
The new library is in scope, and ready to go.<br />
<br />
=== More complex build systems ===<br />
<br />
For larger projects, you may want to store source trees in subdirectories. This can be done simply by creating a directory -- for example, "src" -- into which you will put your src tree.<br />
<br />
To have Cabal find this code, you add the following line to your Cabal<br />
file:<br />
<br />
hs-source-dirs: src<br />
<br />
You can also set up Cabal to run configure scripts, among other features. For more information consult the<br />
[http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html Cabal documentation].<br />
<br />
== Automation ==<br />
<br />
A tool to automatically populate a new cabal project is available:<br />
<br />
cabal install mkcabal<br />
<br />
Usage is:<br />
<br />
<code><br />
$ mkcabal<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created Setup.lhs and haq.cabal<br />
$ ls<br />
Haq.hs LICENSE Setup.lhs _darcs dist haq.cabal<br />
</code><br />
<br />
which will fill out some stub Cabal files for the project 'haq'. <br />
<br />
To create an entirely new project tree:<br />
<br />
<code><br />
$ mkcabal --init-project<br />
Project name: haq<br />
What license ["GPL","LGPL","BSD3","BSD4","PublicDomain","AllRightsReserved"] ["BSD3"]: <br />
What kind of project [Executable,Library] [Executable]: <br />
Is this your name? - "Don Stewart " [Y/n]: <br />
Is this your email address? - "<dons@cse.unsw.edu.au>" [Y/n]: <br />
Created new project directory: haq<br />
$ cd haq<br />
$ ls<br />
Haq.hs LICENSE README Setup.lhs haq.cabal<br />
</code><br />
<br />
== Licenses ==<br />
<br />
Code for the common base library package must be BSD licensed. Otherwise, it<br />
is entirely up to you as the author.<br />
Choose a licence (inspired by [http://www.dina.dk/~abraham/rants/license.html this]).<br />
Check the licences of things you use (both other Haskell packages and C<br />
libraries), since these may impose conditions you must follow.<br />
Use the same licence as related projects, where possible. The Haskell community is<br />
split into 2 camps, roughly: those who release everything under BSD, and<br />
(L)GPLers. Some Haskellers recommend avoiding LGPL, due to cross-module optimisation<br />
issues. Like many licensing questions, this advice is controversial. Several Haskell projects<br />
(wxHaskell, HaXml, etc) use the LGPL with an extra permissive clause which gets round the<br />
cross-module optimisation problem.<br />
<br />
== Releases ==<br />
<br />
It's important to release your code as stable, tagged tarballs. Don't<br />
just [http://awayrepl.blogspot.com/2006/11/we-dont-do-releases.html rely on darcs for distribution].<br />
<br />
* '''darcs dist''' generates tarballs directly from a darcs repository<br />
<br />
For example:<br />
<br />
$ cd fps<br />
$ ls <br />
Data LICENSE README Setup.hs TODO _darcs cbits dist fps.cabal tests<br />
$ darcs dist -d fps-0.8<br />
Created dist as fps-0.8.tar.gz<br />
<br />
You can now just post your fps-0.8.tar.gz<br />
<br />
You can also have darcs do the equivalent of 'daily snapshots' for you by using a post-hook.<br />
<br />
put the following in _darcs/prefs/defaults:<br />
apply posthook darcs dist<br />
apply run-posthook<br />
<br />
Advice:<br />
* Tag each release using '''darcs tag'''. For example:<br />
<br />
$ darcs tag 0.8<br />
Finished tagging patch 'TAG 0.8'<br />
<br />
Then people can <tt>darcs pull --partial -t 0.8</tt>, to get just the tagged version (and not the entire history).<br />
<br />
== Hosting ==<br />
<br />
Hosting for repos is available from the Haskell community server:<br />
<br />
http://community.haskell.org/<br />
<br />
A Darcs repository can be published simply by making it available from a<br />
web page.<br />
<br />
== Web page ==<br />
<br />
Create a web page documenting your project! An easy way to do this is to<br />
add a project specific page to [[Haskell|the Haskell wiki]]<br />
<br />
== The user experience ==<br />
<br />
When developing a new Haskell library, it is important to remember how the user expects to be able to build and use a library.<br />
<br />
=== Introductory information and build guide ===<br />
<br />
A typical library user expects to:<br />
<br />
# Visit [[Haskell|Haskell.org]]<br />
# Find the library/program they are looking for:<br />
## if not found, try mailing list; <br />
## if it is hidden, try improving the documentation on haskell.org;<br />
## if it does not exist, try contributing code and documentation) <br />
# Download<br />
# Build and install<br />
# Enjoy<br />
<br />
Each of these steps can pose potential road blocks, and code authors can<br />
do a lot to help code users avoid such blocks. Steps 1..2 may be easy enough, and many coders and users are mainly concerned with step 5. Steps 3..4 are the ones that often get in the way. In particular, the<br />
following questions should have clear answers:<br />
<br />
* Which is the latest version? <br />
* What state is it in? <br />
* What are its aims? <br />
* Where is the documentation?<br />
* Which is the right version for given OS and Haskell implementation?<br />
* How is it packaged, and what tools are needed to get and unpack it?<br />
* How is it installed, and what tools are needed to install it?<br />
* How do we handle dependencies?<br />
* How do we provide/acquire the knowledge and tool-chains needed?<br />
<br />
The best place to answer these questions is a README file,<br />
distributed with the library or application, and often accompanied with<br />
similar text on a more extensive web page.<br />
<br />
=== Tutorials ===<br />
<br />
Generated haddock documentation is usually not enough to help new<br />
programmers learn how to use a library. You must also provide accompanying examples, and even tutorials about the library.<br />
<br />
Please consider providing example code for your library or application. The code should be type-correct and well-commented.<br />
<br />
== Program structure ==<br />
<br />
Monad transformers are very useful for programming in the large,<br />
encapsulating state, and controlling side effects. To learn more about this approach, try [http://user.cs.tu-berlin.de/~magr/pub/Transformers.en.html Monad Transformers Step by Step].<br />
<br />
== Publicity ==<br />
<br />
The best code in the world is meaningless if nobody knows about it. The<br />
process to follow once you've tagged and released your code is:<br />
<br />
=== Join the community ===<br />
<br />
If you haven't already, join the community. The best way to do this is to [http://haskell.org/haskellwiki/Mailing_lists subscribe] to at least haskell-cafe@ and haskell@ mailing lists. Joining the [[IRC_channel|#haskell IRC channel]] is also an excellent idea.<br />
<br />
=== Announce your project on haskell@ ===<br />
<br />
Most important: announce your project releases to the haskell@haskell.org mailing list. Tag your email subject line with "ANNOUNCE: ...". This ensure it will then make it into the [http://haskell.org/haskellwiki/HWN Haskell Weekly News]. To be doubly sure, you can email the release text to the [[HWN|HWN editor]].<br />
<br />
=== Add your code to the public collections ===<br />
<br />
* Add your library or application to the [[Libraries and tools]] page, under the relevant category, so people can find it.<br />
<br />
* If your release is a Cabal package, add it to the [http://hackage.haskell.org/packages/hackage.html Hackage database] (Haskell's CPAN wanna-be).<br />
<br />
=== Blog about it ===<br />
<br />
Blog about it! Blog about your new code on [http://planet.haskell.org Planet Haskell].<br />
Write about your project in your blog, then email the [http://planet.haskell.org/ Planet Haskell] maintainer (ibid on [[IRC channel|#haskell]]) the RSS feed url for your blog<br />
<br />
== Example ==<br />
<br />
[http://cgi.cse.unsw.edu.au/~dons/blog/2006/12/11#release-a-library-today A complete example] of writing, packaging and releasing a new Haskell library under this process has been documented.<br />
<br />
[[Category:Community]]<br />
[[Category:Tutorials]]</div>Amy de B