ML Dialects and Haskell: SML, OCaml, F#, Haskell - Hyperpolyglot
Hyperpolyglot
ML Dialects and Haskell: SML, OCaml, F#, Haskell
a side-by-side reference sheet
grammar and invocation | variables and expressions | arithmetic and logic | strings | dates and time | arrays | lists | tuples | dictionaries | functions | execution control | exceptions | concurrency | file handles | files | directories | processes and environment | libraries and namespaces | user-defined types | objects | inheritance and polymorphism | net and web | unit tests | debugging and profiling | repl
sml<br>ocaml<br>f#<br>haskell
version used
SML NJ 110<br>4.0<br>F# 3.0
Mono 3.2<br>7.4
show version
displayed at startup<br>$ ocaml -version<br>$ fsharpi --help<br>$ ghc --version
grammar and invocation
sml<br>ocaml<br>f#<br>haskell
interpreter
$ echo 'print_endline "hello"' > hello.ml
$ ocaml hello.ml<br>$ cat EOF > hello.fs
module hello
let main = printfn "hello"
EOF
$ fsharpi --quiet --exec hello.fs<br>$ echo 'main = putStrLn "hello"' > hello.hs
$ runghc hello.hs
shebang
$ cat EOF > hello.ml
#!/usr/bin/env ocaml
print_endline "hello";;
EOF
$ chmod +x hello.ml
$ ./hello.ml<br>$ cat EOF > hello.fs
#light (*
exec fsharpi --exec $0 --quiet
*)
module hello
printfn "hello"
EOF
$ chmod +x hello.fs
$ ./hello.fs<br>$ cat EOF > hello.hs
#!/usr/bin/env runghc
main = putStrLn "hello"
EOF
$ chmod +x hello.hs
$ ./hello.hs
bytecode compiler and interpreter
$ echo 'print_endline "hello";;' > hello.ml
$ ocamlc -o hello hello.ml
$ ocamlrun hello<br>$ echo 'printfn "hello"' > hello.fs
$ fsharpc hello.fs
$ mono hello.exe<br>none
native compiler
$ echo 'print_endline "hello";;' > hello.ml
$ ocamlopt hello.ml -o hello
$ ./hello<br>none<br>$ echo 'main = putStrLn "hello"' > hello.hs
$ ghc -o hello hello.hs
$ ./hello
library which is always imported
Pervasives<br>Core<br>Prelude
statement terminator<br>;;<br>;;<br>next line has equal or less indentation, or ;
blocks<br>( expr ; … )<br>( expr ; … )
begin expr ; … end<br>( expr ; … )
begin expr ; … end<br>offside rule or { }
end-of-line comment<br>none<br>none<br>// comment<br>-- comment
multiple line comment<br>(* comment
another comment *)<br>(* comment
another comment *)<br>(* comment
another comment *)<br>{- comment
another comment -}
variables and expressions
sml<br>ocaml<br>f#<br>haskell
write-once variable
val a = 3;<br>let n = 1 + 2;;<br>let n = 1 + 2<br>n = 3
modifiable variable<br>val a = ref 3;
a := 4;
!a + 7;<br>let n = ref 3;;
n := 4;;
!n + 7;;<br>let n = ref 3
n := 4
!n + 7
unit type and value<br>unit
()<br>unit
()<br>unit
()<br>()
()
conditional expression<br>val x = 3;
if x<br>let n = -3;;
let absn = if n<br>let n = -3
let absn = if n<br>n = -3
let absn = if n
branch type mismatch<br>(* compilation error: *)
if true then "hello" else 3;<br>(* compilation error: *)
if true then "hello" else 3;;<br>(* compilation error: *)
if true then "hello" else 3<br>-- compilation error:
if True then "hello" else 3
null
NONE<br>None<br>None
Also this value returned by .NET library functions. It has a type distinct from None:
null<br>Nothing
nullable type<br>type list_option_int = int option list;
val list = [SOME 3,NONE, SOME ~4];<br>type list_option_int = int option list;;
let list = [Some 3; None; Some (-4)];;
list = [Just(3), Nothing, Just(-4)]
null test
match foo with
| None -> true
| _ -> false;;
coalesce<br>val foo = SOME 3;
(* raises exception if NONE: *)
valOf foo;
(* evaluates to 0 if NONE: *)
getOpt (foo, 0);<br>match foo with
| None -> 0
| Some n -> n;;
import Data.Maybe
let foo = Just(3)
raises exception if Nothing:
fromJust foo
let intId x = x
evaluates to 0 if Nothing:
maybe 0 intId foo
nullif
match foo with
| -999 -> None
| n -> Some n;;
expression type declaration
float 1<br>float 1<br>1 :: Double
let ... in ...<br>val z =
let
val x = 3.0
val y = 2.0 * x
in
x * y
end;<br>let z =
let x = 3.0 in
let y = 2.0 *. x in
x *. y;;<br>let z =
let x = 3.0 in
let y = 2.0 * x in
x * y<br>z = let x = 3.0
y = 2.0 * x
in x * y
where<br>none<br>none<br>none<br>z = x * y
where x = 3.0
y = 2.0 * x
arithmetic and logic
sml<br>ocaml<br>f#<br>haskell
boolean type
bool<br>bool<br>bool<br>Bool
true and false
true false<br>true false<br>true false<br>True False
logical operators<br>andalso orelse not<br>&& || not<br>&& || not<br>&& || not
relational operators<br>= <> =<br>= <> =<br>= <> =<br>== /= =
min and max
min 1 2
max 1 2<br>min 1 2
max 1 2<br>min 1 2
max 1 2
integer type<br>int<br>int
other integer types:
int32 int64 nativeint<br>int
other integer types:
int32 int64 nativeint<br>Integer
integer literal<br>negative integer:
~4<br>int, int64, and nativeint literals:
12 12L 12n
literals can contain underscores:
1_000_000
this parses as an expression:
-4<br>-4<br>an expression, not a literal:
-4
float type<br>real<br>float<br>float<br>Double
integer operators<br>+ - * div mod<br>+ - * / mod
mod //is an infix operator<br>+ - * / %<br>+ - * div rem
div and rem are functions, not infix operators
float operators
+ - * /<br>+. -. *. /.<br>+ - * /<br>+ - * /
add integer and float<br>real 3 + 7.0;<br>float 3 +. 7.0<br>float 3 + 7.0<br>3 + 7.0
integer division
and remainder<br>7 div 3
7 mod 3
real 7 /...