[Haskell-cafe] Re: What makes Haskell difficult as .NET?

C. McCann cam at uptoisomorphism.net
Fri May 14 22:54:34 EDT 2010


On Fri, May 14, 2010 at 8:39 PM, Maciej Piechotka <uzytkownik2 at gmail.com> wrote:
> 1. Haskell Class/Type famillies/... are conceptually different then
> classes and interfaces.

I believe interfaces would be roughly equivalent to the subset of
single-parameter type classes such that:
  - All type class methods are functions
  - The first argument of each function is the class's type parameter,
fully applied to any type parameters it needs
  - The class's type parameter appears nowhere else

Painfully limited, but better than nothing. This would mostly make it
problematic to export Haskell functions with type class constraints to
other .NET languages, though. I suspect large sections of the .NET
libraries could be expressed in Haskell without too much trouble
(well, besides everything being in IO), except that getting Haskell to
interact nicely with the concept of subtyping in inheritance
hierarchies might be awkward. Also potentially problematic is that (if
memory serves me) .NET can only handle type parameters with kind *,
which excludes types parameterized by type constructors, such as monad
transformers.

Irritatingly, a lot of stuff in the .NET framework is almost, but not
quite, equivalent to some really key bits of Haskell. For instance,
Enumerable.Select<A,B>(IEnumerable<A>, Func<A,B>) is almost fmap, but
returns an existential type instead. I guess IEnumerable<T> is
something akin to Foldable, with cheap kludgy imitations of fmap and
(>>=) bolted on after the fact.

Explicit type checks might be necessary in places as well, to deal
with .NET's feeble and unreliable type system. Some boilerplate
involving Data.Typeable/Data.Dynamic ought to suffice.

> 2. As .Net does not differentiate between IO a and a Haskell cannot feel
> completely native (hand-made FFI or everything in IO)

Wouldn't be any worse than using most C bindings in Haskell as is. Or
using a lot of .NET libraries in F#, to be honest, if you try to write
functional-idiomatic instead of quasi-imperative code.

Though, considering the near-omnipresent possibility of null
references, most .NET functions would actually need to return
something of the form "IO (Maybe a)".

> 3. .Net does differentiate between variables and functions with 0
> arguments.

Yes, though the latter are easy enough to use. Property getters are
nullary functions, likewise the Func<TResult> delegate type. You can
even write nullary lambda expressions as "() => ...", though "nullary
lambda abstraction" is kind of a contradiction in terms.

A combination of a nullary pure function and a mutable static variable
to cache the result of evaluating it would provide something similar
to lazy terms in Haskell.

> 4. .Net types are not lazy. String is not [Char]. Arrays are used in
> many places.

On the other hand, many of the hot new features on the .NET platform
are built around lazy collections with IEnumerable<T>, which is
primarily used as if it were the list monad (e.g., LINQ syntax being
sort of a monad comprehension).

In summary: So close, yet so far. It'd probably work just well enough
to be "viable", but be too painful to be enjoyable. I use C# at the
day job, so I notice these things often...

- C.


More information about the Haskell-Cafe mailing list