

Trying Haskell - chegra84
http://chestergrant.posterous.com/trying-out-haskell

======
Peaker
Haskell's type system can also express interesting things most languages' type
systems can't.

For example:

[https://github.com/yairchu/red-black-
tree/blob/master/AvlTre...](https://github.com/yairchu/red-black-
tree/blob/master/AvlTree.hs) \-- in lines 13..21, an AVLTree type is defined
-- with its invariants encoded in the type system. If there's a mistake in
these 9 lines, you may get a wrong program. But the nice thing is that if you
get just these 9 lines right -- then the hundreds of lines below it that
implement an AVL tree __cannot get the AVL invariants wrong __.

The same is also true for Red Black Trees: [https://github.com/yairchu/red-
black-tree/blob/master/RedBla...](https://github.com/yairchu/red-black-
tree/blob/master/RedBlackTree.hs)

Lines 26..36 inclusive encode the RBTree type such that the invariants are
enforced by the type-checker.

In case this is unclear: the type-checker enforcing the correctness of the
invariants is at _compile-time_. A running program is a correct program, at
least from the invariants' perspective.

~~~
billmcneale
This might be beautiful code but come on, not a single comment?

~~~
silentbicycle
See those type declarations? _Those are comments._ Comments that are
automatically checked.

~~~
Zaak
On the one hand, I agree. On the other hand, a type declaration cannot
possibly tell you /why/ unless the type system encodes a significant portion
of our physical world.

This encoding is left as an exercise for the reader.

~~~
silentbicycle
Agreed, generally. I'd say comments are to express things the code itself
cannot. More expressive languages can get by with good naming, some
declarations, and clear idioms in many cases.

The most useful kind of comments are "why" comments, about why specific design
trade-offs were chosen.

------
Tiomaidh
"Oh look, Haskell is great! Why? Static typing and concise code and no side
effects!"

I don't disagree on any particular point, but this is hardly news (on HN, at
least), and is rather lacking in substance.

~~~
danieldk
Indeed. Also, rewriting base library functionality is bad ;):

[http://www.haskell.org/ghc/docs/7.0.2/html/libraries/base-4....](http://www.haskell.org/ghc/docs/7.0.2/html/libraries/base-4.3.1.0/Data-
List.html#v:permutations)

~~~
eru
Unless it's just an exercise or done for fun.

------
ionfish
Obligatory comment pointing out that the fabled "quicksort" example in Haskell
is not actually quicksort proper since it's not in-place.

~~~
chris_j
Is it actually possible to implement quicksort in a pure functional language
like Haskell (with immutable data structures)? Sorting in place would seem to
involve mutating the list every time two values are swapped.

~~~
danieldk
Yes. For example, the vector package provides mutable arrays:

<http://hackage.haskell.org/package/vector-0.7.0.1>

Mutability is attained by using the ST monad. The ST monad uses mutable
memory, but since it does not allow other interactions with the outside world,
its value can be extracted (unlike the IO monad). When you are done with the
modification of the vector, it can be frozen to obtain a pure vector.

The IO monad can also be used, but not if you want to return a pure value.

A good tutorial can be found at:

[http://www.haskell.org/haskellwiki/Numeric_Haskell:_A_Vector...](http://www.haskell.org/haskellwiki/Numeric_Haskell:_A_Vector_Tutorial)

I used mutable vectors in the ST monad in maximum entropy training software,
and they are really performant.

~~~
KirinDave
What blew my mind about the ST monad is that despite its promise of single-
threading, it still allows for recursive division of labor.

I was like, "Wait. Wait. Waaaiiiitt. How does it do that?"

------
pdhborges
C++ quicksort :|

    
    
        #include <algorithm>
        #include <iterator>
        #include <functional>
        using namespace std;
     
        template <typename T>
        void sort(T begin, T end) {
            if (begin != end) {
                T middle = partition (begin, end,   bind2nd(less<iterator_traits<T>::value_type>(), *begin));
                sort (begin, middle);
                sort (max(begin + 1, middle), end);
            }
        }
    

from wikipedia

~~~
chc
His version is explicit, sort of a C++ translation of the C algorithm (though
still a bit longer than necessary even for C). I think he meant to imply "in
simple C++ without STL." The awkwardness of partition() is not quite enough to
overcome the LOC savings, but it's making a good effort.

The Haskell version also refrains from importing the equivalent Data.List,
which would allow us to define `more` and `less` as simply `partition (< x)
xs`.

