[racket] Typed Racket vs. Haskell

From: David Van Horn (dvanhorn at ccs.neu.edu)
Date: Tue Sep 18 16:53:36 EDT 2012

On 9/18/12 4:08 PM, thorsopia at lavabit.com wrote:
>> It's also possible to write Typed Racket programs "types first", like
>> one would in Haskell, and I sometimes do. The "sums-of-products"
>> programming style of Haskell and ML can be expressed easily with Typed
>> Racket's structs and union types. You can also mix and match between
>> "Haskell" and "Racket" styles of programming, and it will all work.
>
> Are you talking about this?
>
> We have already seen the : type annotation form. This is useful for
> definitions, at both the top level of a module
>
> (: x Number)
> (define x 7)
>
> and in an internal definition
>
> (let ()
>    (: x Number)
>    (define x 7)
>    (add1 x))
>
> http://docs.racket-lang.org/ts-guide/more.html#(part._.Annotating_.Definitions)

No, by "types first" I think John and Vincent are talking about a 
conceptual order.  I would phrase it a little more subtly: an ML (or 
Haskell) programmer writes their types, then their programs (as you 
must); a TR programmer thinks about their data, writes down a program, 
then writes down the types (describing the data) they had in mind in the 
first place (and often were written down as comments).  Vincent is 
pointing out that writing TR programs in the other order works just 
fine, too.  The flexibility is one of the best things about TR: you get 
to choose how much of your program is typed and this can evolve over time.

There's also a style to types that's different.  Since Racket 
programmers often think in terms of union types, it was really important 
TR supported union types.  It was also important to support the kind of 
control flow based on predicates that discriminate between members of a 
union, hence the occurrence typing features.  In ML or Haskell, you 
would instead use _disjoint_ unions and pattern matching against 
constructors.  As Vincent said, you can program in that style in TR, 
too, but that style is often not what you would have written in Racket 
in the first place.

A good exercise to get the feel of both styles is to develop a data 
definition for XML expressions or something similar.  Try it out first 
in Racket, then TR.  Then re-develop the program in Haskell.  You'll 
notice that in one, you probably have something like

;; A XExpr is one of
;; - String
;; - Number
;; - ...

and programs look like:

(define (xexpr-function x)
   (cond [(string? x) ... x is a string]
         [(number? x) ... x is a number]
         ...))

And in the other you'll have (OK, ML since I know it better):

datatype XExpr = Str of string | Num of real | ...

and programs:

fun xexprfunction Str(s) = ... s is a string
   | xexprfunction Num(n) = ... n is a real
   | ...

The latter style you can always recreate in TR using structs and match, 
but the other direction won't work.

David


Posted on the users mailing list.