Ocaml and Haskell

7 views
Skip to first unread message

David Richards

unread,
Mar 27, 2008, 4:00:48 AM3/27/08
to pdxfunc
So, I've got a project that is going to need some pretty heavy data
processing. It will implement various data mining methodologies. I
decided to pick up a functional programming language to do the heavy
lifting. I've been reading around, and had decided to learn Ocaml.
But, I still have a lingering question whether Haskell would be a
better investment of my time. The best comparison I've found between
these two languages basically concluded that a programmer had to be
more aware of his style with Haskell to write code as effecient as
code more naturally written in Ocaml. It wasn't a limitation of
Haskell, but that fast code is easier to write in Ocaml due to Ocaml's
parser.

I don't really know much about either language. I've heard that
Haskell is a "pure" functional language, where Ocaml's enhancements of
the past decade or so have added side effects. But, besides a
dogmatic belief in "one right way", are there real dangers for writing
in a less pure form? Are there practical tradeoffs I should consider?

What about libraries of code. Haskell certainly has more people's
attention. I've browsed around, and there seem to be quite a few
libraries available in Haskell, compared to Ocaml.

Anyway, I would greatly appreciate any insight you can add to my
questions.

Thanks in advance,

David Richards

znmeb

unread,
Mar 27, 2008, 10:44:49 AM3/27/08
to pdxfunc
Well ... given the compute-intensive nature of data mining, I'd
propose a third alternative -- Erlang. There are two main reasons for
this:

1. Erlang's main claim to fame is industrial strength fine-grained
concurrency. If this job gets really big, you're going to want to
throw lots of cores and RAM at it, and I don't think anything can
touch Erlang in this arena except high-effort C programming.

2. Erlang includes an in-core database called Mnesia. Again, you may
end up wanting to throw hardware at this, and Mnesia will be
blindingly fast compared to some of the alternatives.

Phil Tomson

unread,
Mar 27, 2008, 11:36:46 AM3/27/08
to pdx...@googlegroups.com

I've been learning OCaml because I had a project that needed high
performance and OCaml tends to do quite well in that regard. For now
OCaml still has the performance edge, though Haskell seems to be
steadily closing the gap.

I also tend to think that if you're new to functional programming (as
I am) it can be nice to be able to fall back on imperative programming
where needed - this is just a pragmatic consideration on my part. I
also tend to like the ability to to OO (the 'O' in OCaml) as that's a
familiar paradigm.

Haskell does seem to be getting more mindshare now, but from what I've
heard there are probably more paid OCaml (and *ML ) programmers than
there are paid Haskell programmers - could be changing, though. OCaml
tends to get a lot of use in the financial trading (quants) space -
for example Janes St. Capital, a London trading firm employs a lot of
OCaml programmers. They recently started an OCaml blog:
http://ocaml.janestcapital.com/ Some good posts there already.

Phil

Phil Tomson

unread,
Mar 27, 2008, 11:44:53 AM3/27/08
to pdx...@googlegroups.com

If concurrency is a requirement then perhaps JoCaml should also be
investigated. Mauricio Fernandez did some comparisons and shares his
conclusions on his eigenclass blog:
http://eigenclass.org/hiki/wide-finder-conclusions

Some quotes:

" * we cannot dismiss constant factors. JoCaml code written by an
individual in an afternoon can perform better than Erlang code refined
over the course of one month by Erlang experts*2 on a per-core basis,
while scaling just as well.

* JoCaml allows to express and reason about concurrent and
distributed systems at very high level, leaving little place for the
sort of bugs that infest code written with threads and shared state.
(I have written a couple fault-tolerant systems in JoCaml that would
have been much harder with threads.)
* Erlang's major strength is fault-tolerance, scalability, etc.,
not raw performance; promoting Erlang by saying that it will be
"faster given enough cores" is disingenuous because it conceals the
existence of alternatives like JoCaml that can scale just as well but
perform much better per core. "

I haven't tried JoCaml yet, but it sounds like it's worth a look.
Maybe it would be a good topic for a pdxfunc presentation?

Phil

Paul A. Steckler

unread,
Mar 27, 2008, 12:01:28 PM3/27/08
to pdx...@googlegroups.com
On Thu, Mar 27, 2008 at 1:00 AM, David Richards
<davidlamo...@gmail.com> wrote:
> So, I've got a project that is going to need some pretty heavy data
> processing. It will implement various data mining methodologies. I
> decided to pick up a functional programming language to do the heavy
> lifting. I've been reading around, and had decided to learn Ocaml.
> But, I still have a lingering question whether Haskell would be a
> better investment of my time. The best comparison I've found between
> these two languages basically concluded that a programmer had to be
> more aware of his style with Haskell to write code as effecient as
> code more naturally written in Ocaml. It wasn't a limitation of
> Haskell, but that fast code is easier to write in Ocaml due to Ocaml's
> parser.

You haven't said what it is you're trying to write.

If you think you may need infinite data structures, Haskell is a win.
If you want speed of compiled code, OCaml is a win.

Haskell has a more expressive type system, so some things are easier
to write in it than in OCaml. For example, "deriving (Show)" makes life
much easier when you want to print out data.

I've used both languages a fair amount, and both are pleasant to program in.

-- Paul

Justin Bailey

unread,
Mar 27, 2008, 12:08:50 PM3/27/08
to pdx...@googlegroups.com
On Thu, Mar 27, 2008 at 1:00 AM, David Richards
<davidlamo...@gmail.com> wrote:
> these two languages basically concluded that a programmer had to be
> more aware of his style with Haskell to write code as effecient as
> code more naturally written in Ocaml. It wasn't a limitation of
> Haskell, but that fast code is easier to write in Ocaml due to Ocaml's
> parser.
>

I don't think the parser has anything to do with it, but it is easy to
write leaky programs in Haskell. If you are processing huge amounts of
data you can really get yourself in trouble.

Fortunately, these kind of problems are easy to detect and (when
profiling early and often) not too hard to track down. Laziness can
make your program very space effecient as data doesn't have to be
loaded until it's needed. Assuming your are processing your data
row-at-a-time (or line-at-a-time), it's very possible to write a
program that uses very little memory. If you are loading data from a
database, Takusen is a well-supported library that supports lazy
queries. If data is coming from the filesystem, GHC's file I/O is lazy
by default.

On the issue of parallelism, GHC has a very nice set of parallel
primitives. Note these are not *concurrency* primitives, in the sense
of remote processes working together, but parallelizing your code to
run on multiple cores on the same machine. There isn't a lot written
on how to use them but they do work.

>
> I don't really know much about either language. I've heard that
> Haskell is a "pure" functional language, where Ocaml's enhancements of
> the past decade or so have added side effects. But, besides a
> dogmatic belief in "one right way", are there real dangers for writing
> in a less pure form? Are there practical tradeoffs I should consider?

One measurable advantage of purity is confidence in the behavior of
your code. If a function has side effects, they show up in the type
and you can't hide from it. Purity gives you isolation of effects and
really helps isolate bugs. You can narrow in on one function without
worrying about global side effects (unless, of course, that function
uses side-effects).

Search the internet for the paper "Wearing the hair shirt" - it's a
great discussion of the advantages of a pure, lazy functional
language.

>
> What about libraries of code. Haskell certainly has more people's
> attention. I've browsed around, and there seem to be quite a few
> libraries available in Haskell, compared to Ocaml.

http://hackage.haskell.org/packages/archive/pkg-list.html is a good
place to start looking.

>
> Anyway, I would greatly appreciate any insight you can add to my
> questions.

One caveat is that learning Haskell is definitely a character-building
exercise (in the sense your parents used to tell you). I came from an
OO background with no functional programming experience. The learning
curve was very steep. However, I feel I am a much better programmer
for it and am glad to have done it.

Justin

Phil Tomson

unread,
Mar 27, 2008, 12:16:32 PM3/27/08
to pdx...@googlegroups.com
On Thu, Mar 27, 2008 at 9:08 AM, Justin Bailey <jgba...@gmail.com> wrote:

>
> On the issue of parallelism, GHC has a very nice set of parallel
> primitives. Note these are not *concurrency* primitives, in the sense
> of remote processes working together, but parallelizing your code to
> run on multiple cores on the same machine.

I've heard rumors to this effect...

> There isn't a lot written
> on how to use them but they do work.
>

Have you used these features and if so would you be interested in
doing a presentation on them?


>
> One caveat is that learning Haskell is definitely a character-building
> exercise (in the sense your parents used to tell you). I came from an
> OO background with no functional programming experience. The learning
> curve was very steep.

This is part of what led me to learn OCaml first (still learning it).
I'm hoping that Haskell will be a bit less daunting after I've done
some OCaml ;-)

Oh, the other thing that tipped the scales in favor of learning OCaml
first for me was the rocaml bridge between Ruby and OCaml - I don't
know if thats a consideration for the original poster or not. Could
be nice if you're using Rails for your Web programming and you want
OCaml for backend, highspeed processing.

Phil

Justin Bailey

unread,
Mar 27, 2008, 12:35:50 PM3/27/08
to pdx...@googlegroups.com
On Thu, Mar 27, 2008 at 9:16 AM, Phil Tomson <philt...@gmail.com> wrote:
> > There isn't a lot written
> > on how to use them but they do work.
> >
>
> Have you used these features and if so would you be interested in
> doing a presentation on them?

I wish I had used them enough to say something useful, but I don't
think I have. Don Stewart wrote a great blog post about them a bit
ago:

http://cgi.cse.unsw.edu.au/~dons/blog/2007/11/29#smoking-4core
http://www.cse.unsw.edu.au/~dons/blog/2007/11/29#smoking

Justin

Kevin Scaldeferri

unread,
Mar 27, 2008, 12:54:55 PM3/27/08
to pdx...@googlegroups.com

On Mar 27, 2008, at 8:44 AM, Phil Tomson wrote:

>
>
> If concurrency is a requirement then perhaps JoCaml should also be
> investigated. Mauricio Fernandez did some comparisons and shares his
> conclusions on his eigenclass blog:
> http://eigenclass.org/hiki/wide-finder-conclusions
>
> Some quotes:
>
> " * we cannot dismiss constant factors. JoCaml code written by an
> individual in an afternoon can perform better than Erlang code refined
> over the course of one month by Erlang experts*2 on a per-core basis,
> while scaling just as well.
>

> * Erlang's major strength is fault-tolerance, scalability, etc.,
> not raw performance; promoting Erlang by saying that it will be
> "faster given enough cores" is disingenuous because it conceals the
> existence of alternatives like JoCaml that can scale just as well but
> perform much better per core. "


It should probably be pointed out that Wide Finder is just one
benchmark, which happens to emphasize some areas which Erlang is
notorious weak on (i.e. not designed with them in mind). It's also a
short-running data processing task. If the task were running a
complex system for a year with no downtime, the "constant factors"
would likely run the other way. A program written in an afternoon in
Erlang using OTP will likely satisfy this requirement better than what
two JoCaml experts can produce in a month.

(Also, for the record, the current wide finder front runner is.... Perl)


-kevin

Kevin Scaldeferri

unread,
Mar 27, 2008, 12:56:39 PM3/27/08
to pdx...@googlegroups.com

On Mar 27, 2008, at 9:16 AM, Phil Tomson wrote:

>
>
>>
>> One caveat is that learning Haskell is definitely a character-
>> building
>> exercise (in the sense your parents used to tell you). I came from an
>> OO background with no functional programming experience. The learning
>> curve was very steep.
>
> This is part of what led me to learn OCaml first (still learning it).
> I'm hoping that Haskell will be a bit less daunting after I've done
> some OCaml ;-)


I learned OCaml a while before learning Haskell, and I suspect it will
still be rather daunting. But also rewarding!

-kevin

David Richards

unread,
Mar 28, 2008, 5:32:34 AM3/28/08
to pdxfunc
This is amazing, everybody. Somehow, these kinds of discussions have
not top-listed my Google searches, which either points to my laziness
or simply the relative scarcity of functional programming discussions
online. As you have more comments and thoughts, please keep them
coming. I am eagerly chasing down links, building out a mind map of
considerations and thoughts.

I hadn't said a lot about my project. It's not secret or anything.
I've named it GSA, which is just a placeholder at the moment at
rubyforge. Indeed, I have decided to use Ruby as the glue for
everything. I really like some of the peripheral gems that will make
the application work more like a framework quicker and with less
overall effort than chasing down/building these libraries from
scratch. There are also some very large libraries that I know are
bound already for Ruby. Ultimately, the libraries will originate from
about everything: C, C++, Java, Ruby, R, MatLab, and possibly others.
There will be some critical pieces that will be built directly in a
preferred functional language: the result of this research. I just
haven't found implementations to some of the concepts I'll be
exploring.

I'll be digging deeper into what's been discussed. I'm frankly uneasy
with the way I'm managing the state space. But here are a few of the
dynamics of my work:

* I'll be presenting an ontology of ideas to a seminar at school,
hopefully recruiting those in attendance to help me gather
implementations of various algorithms these people have been using.
My professors and I will be asking other systems science programs to
contribute to the ontology.
* This means we'll be getting code in about every language used in
academia, but much of the new algorithm implementations will be done
in the functional language of my choosing.
* Libraries will be rendred executable through some bridge code I'll
be writing in Ruby. This bridge code will bind other libraries to a
common interface. There will also be JRuby and IronRuby instances of
the GSA made available that can make use of wider ranges of libraries.
* Images will be configured and made available for both private server
farms and Amazon's EC2. The production environment has led me to
think about grid programming in a trusted environment, which led me to
Linda, which led me to Rinda, which may lead me to Starfish (a Ruby
gem that wraps Rinda).
* An inference engine will match the problem at hand and the algorithm
implementations available to it, starting and stopping services as
necessary.

But there's a lot of naivety about the kinds of bottlenecks I could
introduce with this kind of architecture. I'm still working on the
premise that the most valuable part of this project is the cooperation
of graduate programs from around the world, but I'm not sure I can get
away with such a loose coupling with the data sources. Haskell,
JoCaml, and Erlang all seem to offer a much tighter integration with
their data sources.

To explore further, I should be sure I understand the tradeoffs
between:

* Haskell and it's support for near infinite data structures and
Takusen
* JoCaml and it's support for concurrency
* Ocaml and it's integration with Ruby, it's high computational
performance, and its relative ease to write safer code
* Erlang and it's integration with Mnesia

I think I'll attack this problem this way:

* I'll read through the ideas you guys have suggested and continue
down this broad road of discovery for a while, changing course if I
need to
* I'll use the functional language I eventually adopt for any
greenfield algorithm implementation only
* If I've painted myself into a corner with my loosely coupled system,
I'll have to write the inference engine in a functional language with
heavy concurrency support and then find a way to get these libraries
all speaking to the same functional language. By that time, however,
I'll have two new advantages: at least some comfort in one of the
above functional languages, and a better idea of just how varied my
third-party libraries will likely be.

I think this discussion has opened my eyes to one of the biggest
issues I've had with this ambitious project: even though I can
probably generalize how data reads and writes can be fed to all sorts
of algorithms in all sorts of libraries with a dynamic language, the
size of the data sets becomes the bottleneck.

I'm not trying to put a capstone on this discussion, it's exactly
addressing some of the real-world tradeoffs you guys have had to deal
with. If you have more thoughts along those lines, please let me
know. Or, if you see me misunderstanding or over-simplifying things,
also please let me know.

Thanks again,

David

znmeb

unread,
Mar 28, 2008, 9:29:10 AM3/28/08
to pdxfunc
David Richards wrote:
> This is amazing, everybody. Somehow, these kinds of discussions have
> not top-listed my Google searches, which either points to my laziness
> or simply the relative scarcity of functional programming discussions
> online. As you have more comments and thoughts, please keep them
> coming. I am eagerly chasing down links, building out a mind map of
> considerations and thoughts.

For all practical purposes, functional programming languages have been
around in "production" as long as imperative ones -- Lisp 1.5 only
lags Fortran II by about three years out of five decades. And yet in a
very real sense, imperative programming has always been "easier" than
functional programming. There are, IMHO, simply fewer people qualified
to discuss functional programming than imperative programming.

[snip]

> Ultimately, the libraries will originate from
> about everything: C, C++, Java, Ruby, R, MatLab, and possibly others.
> There will be some critical pieces that will be built directly in a
> preferred functional language: the result of this research. I just
> haven't found implementations to some of the concepts I'll be
> exploring.

I use R heavily and Matlab not at all. I haven't found much you can't
do in R, and there is an R-Ruby bridge library (rsruby). And Matlab is
a commercial licensed project. There are open source "Matlab-like
environments", however -- Octave, SciLab and FreeMat are the three I
have on Gentoo Linux.

[snip]

> * Libraries will be rendred executable through some bridge code I'll
> be writing in Ruby. This bridge code will bind other libraries to a
> common interface. There will also be JRuby and IronRuby instances of
> the GSA made available that can make use of wider ranges of libraries.

For now, I think IronRuby is safe to ignore. It hasn't turned out to
be as easy to build as a lot of us expected. jRuby is probably a safe
bet on Windows platforms. In addition, you get the Ruby-Java interface
for free,and there is lots of "knowledge management" code written in
Java already.

> * Images will be configured and made available for both private server
> farms and Amazon's EC2. The production environment has led me to
> think about grid programming in a trusted environment, which led me to
> Linda, which led me to Rinda, which may lead me to Starfish (a Ruby
> gem that wraps Rinda).

And Starfish will lead you to Map-Reduce. :)

[snip]

> But there's a lot of naivety about the kinds of bottlenecks I could
> introduce with this kind of architecture. I'm still working on the
> premise that the most valuable part of this project is the cooperation
> of graduate programs from around the world, but I'm not sure I can get
> away with such a loose coupling with the data sources. Haskell,
> JoCaml, and Erlang all seem to offer a much tighter integration with
> their data sources.

I actually think your biggest bottleneck is going to be getting
funding -- there are lots of big players in "knowledge management"
already.:)

[snip]

> I think I'll attack this problem this way:
>
> * I'll read through the ideas you guys have suggested and continue
> down this broad road of discovery for a while, changing course if I
> need to
> * I'll use the functional language I eventually adopt for any
> greenfield algorithm implementation only
> * If I've painted myself into a corner with my loosely coupled system,
> I'll have to write the inference engine in a functional language with
> heavy concurrency support and then find a way to get these libraries
> all speaking to the same functional language. By that time, however,
> I'll have two new advantages: at least some comfort in one of the
> above functional languages, and a better idea of just how varied my
> third-party libraries will likely be.

I'm not sure why you need to write an "inference engine". Aren't there
libraries that do that? In any event, I'll throw another language into
the mix -- Mercury. On my Gentoo system:

* dev-lang/mercury
Latest version available: 0.13.1-r1
Latest version installed: [ Not Installed ]
Unstable version: 0.13.1-r1
Use Flags (stable): -debug -minimal +readline +threads
Size of downloaded files: [no/bad digest]
Homepage: http://www.cs.mu.oz.au/research/mercury/index.html
Description: Mercury is a modern general-purpose logic/
functional programming language
License: GPL-2

* dev-lang/mercury-extras
Latest version available: 0.13.1
Latest version installed: [ Not Installed ]
Unstable version: 0.13.1
Use Flags (stable): -doc -glut -iodbc +ncurses +odbc
+opengl +tcl +tk +xml
Size of downloaded files: [no/bad digest]
Homepage: http://www.cs.mu.oz.au/research/mercury/index.html
Description: Additional libraries and tools that are not part of
the Mercury standard library
License: GPL-2

Mercury is essentially a high-performance re-implementation of Prolog
semantics.

> I think this discussion has opened my eyes to one of the biggest
> issues I've had with this ambitious project: even though I can
> probably generalize how data reads and writes can be fed to all sorts
> of algorithms in all sorts of libraries with a dynamic language, the
> size of the data sets becomes the bottleneck.

I think another challenge will be that you could end up getting
"attached" to one of the many open source tools out there that are
pieces of your puzzle and end up spending your time improving the
tools rather than building your project. :) As far as the size of the
datasets is concerned, Map-Reduce is your friend. :)

Phil Tomson

unread,
Mar 28, 2008, 7:45:20 PM3/28/08
to pdx...@googlegroups.com

Just curious, is there an equivilent to camlp4 in the Haskell world?
Some way of manipulating the AST?

Phil

Paul A. Steckler

unread,
Mar 28, 2008, 8:05:06 PM3/28/08
to pdx...@googlegroups.com
On Fri, Mar 28, 2008 at 4:45 PM, Phil Tomson <philt...@gmail.com> wrote:
> Just curious, is there an equivilent to camlp4 in the Haskell world?
> Some way of manipulating the AST?

Yes, Template Haskell.

Of course, you're better using Lisp or Scheme for this kind of thing. :-)

-- Paul

winterkoninkje

unread,
Mar 28, 2008, 8:41:35 PM3/28/08
to pdxfunc
On Mar 28, 9:29 am, znmeb <zzn...@gmail.com> wrote:
> *  dev-lang/mercury
> *  dev-lang/mercury-extras
>
> Mercury is essentially a high-performance re-implementation of Prolog
> semantics.

One warning about Mercury though is that they've bootstrapped
themselves away from reality. If you don't already have an installed
version, it'll be a challenge getting it (a coworker just finished
trying all of the available snapshots/branches/etc and couldn't get
any of them to bootstrap, much despite the project's claims). Debian's
package system (as I recall) has an old binary version which you can
use, but it's too old to bootstrap newer versions.

> As far as the size of the
> datasets is concerned, Map-Reduce is your friend. :)

If you're using strings at all in your data mining, you should
definitely read Rewriting Haskell Strings <http://www.cse.unsw.edu.au/
~dons/papers/CSL06.html>. The ByteStrings developed there ship with
GHC if you want to use them, but there's also a functional perl in
there about how to make map-reduce and similar patterns more efficient
for many other data structures too.

Phil Tomson

unread,
Mar 28, 2008, 10:58:03 PM3/28/08
to pdx...@googlegroups.com

True.

Let me show an example (in OCaml, but it probably maps to Haskell
pretty well) where metaprogramming seems like it would be a win. I
was going through the OCaml tutorial a while back and decided to
expand their expr type to include a numeric value:

type expr = Plus of expr * expr (* means a + b *)
| Minus of expr * expr (* means a - b *)
| Times of expr * expr (* means a * b *)
| Divide of expr * expr (* means a / b *)
| Value of string (* "x", "y", "n", etc. *)
| Number of int ;; (* I added this one *)

Then I added a reduce function to reduce expressions:

let rec reduce e =
match e with
Times( Number x, Number y) -> Number ( x * y)
| Times( e1, Number y) -> Times( (reduce e1) , Number y)
| Times( Number x, e2) -> Times(Number x , (reduce e2))
| Times( e1, e2) -> Times ( (reduce e1), (reduce e2))
| Plus( Number x, Number y) -> Number (x + y)
| Plus( e1, Number y) -> Plus( (reduce e1) , Number y )
| Plus( Number x, e2) -> Plus( Number x , ( reduce e2) )
| Plus( e1, e2) -> Plus ( (reduce e1), (reduce e2))
| Minus( Number x, Number y) -> Number (x - y)
| Minus( e1, Number y) -> Minus( (reduce e1) , Number y )
| Minus( Number x, e2) -> Minus( Number x , ( reduce e2) )
| Minus( e1, e2) -> Minus ( (reduce e1), (reduce e2))
| Divide( Number x, Number y) -> Number (x / y)
| Divide( e1, Number y) -> Divide( (reduce e1) , Number y )
| Divide( Number x, e2) -> Divide( Number x , ( reduce e2) )
| Divide( e1, e2) -> Divide( (reduce e1), (reduce e2))
| Value v -> Value v
| Number n -> Number n ;;


OK, so if I were doing this in Ruby somehow, I'd think, "you know,
that seems like a lot of duplication" and I'd metaprogram it so that
(if pattern matching were possible in standard Ruby) each of those "|"
options could be generated from some simple one liner given a list of
constructors for the expr type and a list of operators. But camlp4
it's overkill for this sort of thing... In scheme you could write
some sort of macro (though, pattern matching isn't built into scheme
either, nor is strict typing). If I had a more complex type with many
more constructors and more matches I'd be tempted to make some sort of
Ruby DSL to generate this stuff ;-)

Also, is Template Haskell closer to MetaOcaml than it is to camlp4?


Phil

Paul A. Steckler

unread,
Mar 28, 2008, 11:31:37 PM3/28/08
to pdx...@googlegroups.com
On Fri, Mar 28, 2008 at 7:58 PM, Phil Tomson <philt...@gmail.com> wrote:
> In scheme you could write
> some sort of macro (though, pattern matching isn't built into scheme
> either, nor is strict typing).

PLT Scheme (and probably other Scheme implementations) has pattern-matching.
In fact, the match code was just recently re-written for better performance.

-- Paul

Iavor Diatchki

unread,
Mar 30, 2008, 1:38:36 PM3/30/08
to pdx...@googlegroups.com
Hello,
you really don't need meta-programming to remove the duplication in
this case. Here is one way to avoid it (in Haskell, but a very
similar program will work in ML/variants):

data Expr = Prim Op [Expr]
| String String
| Int Int
deriving Show

data Op = Plus | Minus | Times | Divide
deriving Show

prim_op op [Int x, Int y] = Int (op_val x y)
where op_val = case op of
Plus -> (+)
Minus -> (-)
Times -> (*)
Divide -> div

eval e = case e of
Prim op es -> prim_op op (map eval es)
_ -> e


Hope this helps,
Iavor

Phil Tomson

unread,
Apr 3, 2008, 7:26:09 PM4/3/08
to pdx...@googlegroups.com
On Sun, Mar 30, 2008 at 10:38 AM, Iavor Diatchki
<iavor.d...@gmail.com> wrote:
>
> Hello,
> you really don't need meta-programming to remove the duplication in
> this case. Here is one way to avoid it (in Haskell, but a very
> similar program will work in ML/variants):
>
> data Expr = Prim Op [Expr]
> | String String
> | Int Int
> deriving Show
>
> data Op = Plus | Minus | Times | Divide
> deriving Show
>
> prim_op op [Int x, Int y] = Int (op_val x y)
> where op_val = case op of
> Plus -> (+)
> Minus -> (-)
> Times -> (*)
> Divide -> div
>

OK, I've got all of the above in OCaml as:

type op = Plus | Minus | Times | Divide ;;


type expr = Prim of op


| Value of string (* "x", "y", "n", etc. *)
| Number of int ;;

let prim_op op tup =
let op_val = match op with
Plus -> ( + )
| Minus -> ( - )
| Times -> ( * )
| Divide -> ( / ) in
Number( (op_val (fst tup) (snd tup)) ) ;;

(* try it *)
prim_op Plus (2,3) ;; (* -> 5 *)

But I'm a bit stumped as to how to translate this eval from Haskell to Ocaml:

> eval e = case e of
> Prim op es -> prim_op op (map eval es)
> _ -> e
>

any ideas?

Phil

>
> Hope this helps,
> Iavor
>

Iavor Diatchki

unread,
Apr 3, 2008, 9:35:52 PM4/3/08
to pdx...@googlegroups.com
Hi,

Here is the version on ocaml. Your version was almost correct. What I changed:
1) added the argument list for prim ops in "expr"
2) changed the function "prim_op" to work with lists instead of pairs.
Actually, you can do it either way, lists are a bit more general
because you could have prim-ops with different arities.

Hope this helps,
Iavor


type op = Plus | Minus | Times | Divide ;;

type expr = Prim of op * expr list


| Value of string (* "x", "y", "n", etc. *)
| Number of int ;;

let prim_op op [ Number x; Number y ] =


let op_val = match op with
Plus -> ( + )
| Minus -> ( - )
| Times -> ( * )
| Divide -> ( / ) in

Number(op_val x y ) ;;

(* try it *)
prim_op Plus [Number 2; Number 3] ;; (* -> 5 *)

let rec eval e = match e with
Prim (op,es) -> prim_op op (List.map eval es)
| _ -> e ;;

(* try it *)
eval (Prim (Plus, [Prim (Times, [Number 2; Number 3]); Number 7])) ;;

Phil Tomson

unread,
Apr 4, 2008, 1:15:36 AM4/4/08
to pdx...@googlegroups.com
Thanks. So In this case the Haskell and OCaml seem to be quite similar.

Phil

Reply all
Reply to author
Forward
0 new messages