<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Hi,<div><br></div><div>Strangely enough, I did the opposit some time ago. Ocaml is way simpler than haskell, in fact. There is no referential transparency, no laziness (though it can be simulated with "fun ()->x", but the type of a lazy expression is not the same as the reduced expressions), no parallelism (the GC is not parallel). There are no list comprehensions.</div><div>The syntax for pattern matching is simpler but more restrictive, and there are loops. There are also objects, but even good caml programmers (i.e. at ICFP level) do not use it. Also, there are fewer available libraries, due to a quite immature FFI.</div><div><br></div><div>I should also say that the top-level is of much greater help than ghci, and I strongly recommend using tuareg-mode with emacs, which make up a very powerful combination. Have a look at these examples :</div><div><br></div><div>let fact n=</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>if n=0 then 1 else n*(fact (n-1))</div><div><br></div><div>This function is of type Int->Int because the arithmetic operations are monomorphic (there are no typeclasses). If you wanted to do it with Doubles, you would have used *. +. and -. For other types, you would have been on your own ;-)</div><div><br></div><div>let quickSort l=match l with</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>[]->[]</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>| h::t -> <span class="Apple-tab-span" style="white-space:pre"> </span>let (a,b)=List.partition (fun x->x<=h) t in</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>List.append (quickSort a) (h::(quickSort b))</div><div><br></div><div>As you can see, match is pretty close to case, except that it requires | between clauses, because the indentation is not significative. Also, lambda abstractions are called fun x-> instead of \x->. There is a syntactic sugar for combining lambdas and match :</div><div><br></div><div>function []->M</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>| h::t->M'</div><div>which translates as fun x->match x with ...</div><div><br></div><div>You cannot see it here, but camlists do not define variables with indentations as in :</div><div><br></div><div>let <span class="Apple-tab-span" style="white-space:pre"> </span>a=</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>b=</div><div>in</div><div><br></div><div>This would be "let a=... in let b=... in" with any number of lines and arbitrary indentation. Or "let a=... and b=... in", for instance if you want mutually recursive functions. This is because an ocaml file is evaluated in the order in which it is written, which allows for a cool top-level (by the way, the cool emacs command is C-x-e, "evaluate last expression" in tuareg mode).</div><div>The module system seems sometimes obscure, as modules do not correspond always to files, and you can define several modules in a file. You can read <a href="http://caml.inria.fr/pub/docs/manual-ocaml/manual004.html">http://caml.inria.fr/pub/docs/manual-ocaml/manual004.html</a> to get an idea. </div><div><br></div><div>You can define custom types. There is not newtype in haskell, and the keywords for type and data are the same :</div><div><br></div><div>type tree a = Leaf of a | Node of (tree a)*(tree a)</div><div><br></div><div>Then you can match on it :</div><div>match t with</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>Leaf x-></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>Node (x,y)-></div><div><br></div><div>How to do monads ? It is very simple, actually. Some expressions are of type (), with great similarity to IO (). >>= is expressed like in C, with ;</div><div><br></div><div>print_string "This is a string";</div><div>print_int (a+b);</div><div>a</div><div><br></div><div>Would translate in haskell as :</div><div><br></div><div>do</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>putStr "This is a string"</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>print $ a+b</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>return a</div><div><br></div><div>But the typesystem of ocaml does not require you to use monads. Also, you may have notice that there is no $ in ocaml. There is also a very fine exception system :</div><div><br></div><div>exception MyException;</div><div>exception MyException';</div><div>try</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>if a=0 then raise MyException else raise MyException'</div><div>with</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>MyException -> print_string "MyException"</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>| MyException' -> print_string "MyException'"</div><div><span class="Apple-tab-span" style="white-space:pre"> </span></div><div>Which allows you to match the value of what error you program did. The last thing you can use is references and loops :</div><div><br></div><div>for i=0 to n do</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>...</div><div>done;</div><div><br></div><div>let a=ref 10</div><div>while (!a)=0 do</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>print_int (!a);</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>a := (!a)-1</div><div>done;</div><div><br></div><div>Most of the time you use mapM_ in haskell, you can do it with loops and references in ocaml, and you save the memory allocation of the list (which is not a lot, I know). You can also notice that references are much simpler to use than in haskell, due to "implicit monads" and unsafePerformIO everywhere.</div><div><br></div><div>What else ? Records and record updates (you may find this in the manual). And objects : maybe your future boss smokes objects, thus you can learn about this in the manual.</div><div>A good point in ocaml is that the program does, to a large extent, exactly what you write, in the order you write it.Thus, it is often simpler to know where exceptions occur, and performance is less an issue than in haskell. In fact, haskell waited more than ten years before producing fast code, whereas ocaml did it almost from the beginning.</div><div><br></div><div><br></div><div>Good luck !</div><div>Pierre-Etienne</div><meta charset="utf-8"></body></html>