ADT views Re: [Haskell] Views in Haskell

Bulat Ziganshin bulat.ziganshin at gmail.com
Wed Jan 31 13:28:30 EST 2007


Hello David,

Wednesday, January 31, 2007, 7:12:05 PM, you wrote:

>> data Coord = Coord Float Float
>> view of Coord = Polar Float Float where
>>   Polar r d                    =   Coord (r*d) (r+d)    -- construction
>>   Coord x y   | x/=0 || y/=0   =   Polar (x*y) (x+y)    -- matching

> This is somewhat pretty, but in spite of your desire to avoid creating new
> syntax, you have just done so, and in the process made views more limited.
> Pattern matching sytax remains the same, but a new declaration syntax has
> been added.  And now in order to pattern match on a function it needs to
> explicitely be declared as a "view".

yes. among the possible uses for views i clearly prefers the
following: definition of abstract data views that may differ from
actual type representation. moreover, i think that this facility
should be syntactically indistinguishable from ordinary data
constructor patterns in order to simplify learning and using of
language. *defining* view is a rare operation, using it - very common

so my first point is that views should be used in just the same way as
ordinary constructors, both on left and right side:

f (Polar r a) = Polar (r*2) a

Next, i don't think that ability to use any functions in view buy
something important. pattern guards can be used for arbitrary
functions, or such function can be used in view definition. view,
imho, is not a function - it's a two-way conversion between abstract
and real data representation which has one or more alternative
variants - just like Algebraic Data Types. so, when defining a view, i
want to have ability to define exactly all variants alternative to
each other. for another representation, another view should be
created. so

view Polar Float Float of Coord where
  constructor (Polar r a) means (Coord (r*sin a) (r*cos a))
  match pattern (Polar (sqrt(x*x+y*y)) (atan(y/x))) for (Coord x y) where x/=0
                (Polar y (pi/2))                    for (Coord x y) where y>0
                (Polar (-y) (-pi/2))                for (Coord x y) where y<0

of course, my syntax is cumbersome. that is important is that view
definition should be explicit (no arbitrary functions), it should
mention all possible alternatives and provide a way to use the same
constructor name both for construction of new values and matching
existing ones. this all together should allow to transparently use ADT
views instead of plain ADTs

> And unless you are planning to allow one-way views (you don't give any
> examples of that), "view functions" must be invertible, which greatly
> weakens their power.  If you choose to allow one-way views (non-invertible
> functions), then I'd vote for not allowing two-way views, as it adds
> complexity without adding any appreciable gain.

> I don't like your use of capital letters for ordinary functions, I enjoy
> having the syntax tell me whether (Foo 1) might or might not be an
> expensive operation.

the whole idea of abstraction is to not give users any knowledge aside
from algorithmic specifications. when you write (x+y) you don't know
whether this (+) will end in ADD instruction or sending expedition to
Mars :)  why you need low-level control over data matchers exported by
library but not over its functions?

> Finally, you've replaced Simon's explicit incomplete function using Maybe
> with an implicit incomplete function that returns _|_ when the view doesn't
> match.

it's an independent idea that can be used for Simon's syntax or don't
used at all. really, we need Prolog-like backtracking mechanism, i.e.
way to say "this pattern don't match input value, please try the next
alternative". Simon emulated backtracking with Maybe, one can does the
same with return/fail, i figured out one more way - just allow
recursive use of function guards. Here, if all alternatives for Polar
pattern fails, then the whole Polar pattern don't match and we should
try the next alternative. so, the following:

f (Polar r a) = Polar (r*2) a
f (Coord 0 0) = Coord 0 0

should be translated into:

f (Coord x y) | x/=0 = Coord (r*2*sin a) (r*2*cos a)
                         where r = sqrt(x*x+y*y)
                               a = atan(y/x)
f (Coord x y) | y>0  = Coord (r*2*sin a) (r*2*cos a)
                         where r = y
                               a = pi/2
f (Coord x y) | y<0  = Coord (r*2*sin a) (r*2*cos a)
                         where r = -y
                               a = -pi/2
f (Coord 0 0) = Coord 0 0

> I find this rather unappealing.  I certainly prefer *intentionally*
> incomplete functions to return Maybe somthing, rather than just bombing out
> when given invalid input.  I suppose you'll point out that the view Coord
> is a function that you can never explicitely call, but to me that just
> makes things even more confusing.  Now we're defining functions that we can
> only use in pattern matching, but can never call.

i hope that now my idea is clear


-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com



More information about the Haskell-prime mailing list