[Haskell-cafe] FGL instance constraint

Ivan Lazar Miljenovic ivan.miljenovic at gmail.com
Sun May 2 00:41:12 EDT 2010


"Kevin Quick" <quick at sparq.org> writes:
> I was trying to put them on the inside.  Essentially I was trying to
> use the 'a' portion of the LNode as a type that would provide methods
> from which I could reconstruct the shape of the Graph.  Or to put it
> another way, I had a collection of data and I wanted to be able to say
> "this container of data is also useable as a graph" by using class
> operations on the data.
>
> I've discovered an alternative, workable approach to the issue.  After
> coming to terms that the instance of Graph could impose no
> restrictions on the node (or edge) labels and that they were (as you
> previously mentioned) simply "decorators" for the node, I determined
> that I could achieve my goal by writing a converter from "Cls" -> "a
> Graph instance for a" and I simply used Data.Graph.Inductive.Tree as
> the "a Graph instance" portion.
>
> import Data.Graph.Inductive.Tree
>
> clsToGraph :: (Cls a) => B a -> Gr a ()
> clsToGraph b = mkGraph (nodes b) (edges b)
>   where nodes x = ...
>         edges x = ...
>

This is the more typical/idiomatic/proper way of doing it in Haskell;
this means that each function is typically as specific in terms of
constraints as it has to be and no more (which means it's easier to
reuse, and we all like re-using functions!).

> The downside of this, to my procedurally-trained brain is that (1)
> I've now duplicated each 'a' in two different datastructures, and (2)
> I've had to pay--albeit lazily--for the conversion from B to the tree
> container represented by Gr.  The nascent functionaly-trained portion
> of my brain would like to think that GHC (or other) is smart enough to
> not create duplicate copies... I'm not sure that's true though.  I
> think I was probably fooling myself about (2) though: it was always
> there, just more explicitly now.

Not sure how this is any more expensive than specifying that it can only
have values of type a that match the constraint; more specifically you
can have:

clsToGraph :: (Cls a) => B a -> Gr (B a) ()
clsToGraph b = ...

(this of course assumes this makes sense for your data types).

> It's one of the joys of Haskell: it saves your from your own stupid
> ideas.  :-)

Exactly; the type system is a straight jacket (in comparison to
Python's, etc.), but a nice comfortable roomy straight jacket with
plenty of give which lets you do most things but doesn't let you jump
over 10 storey high railings into the traffic on the highway below
(unless you pull out the magic unsafeRemoveStraighJacket function, in
which case all bets are off).

-- 
Ivan Lazar Miljenovic
Ivan.Miljenovic at gmail.com
IvanMiljenovic.wordpress.com


More information about the Haskell-Cafe mailing list