Pattern Matching syntax comparison in Scala, Haskell, ML and OCaml

After writing my last post about Pattern matching in Scala, I was curious about how pattern matching was solved in other languages.

So in this post, I'll use the examples from the last blog post to compare how this would be solved in Scala, Haskell, ML and OCaml.

List example

The first example was to create a recursive function that prints a list of Integers as cons cells. So, let's take a look at how we would solve this using the different languages.

Scala
def pCons(list: List[Int]): String = list match {  
    case Nil => "nil"
    case x::xs => "(" + x + "." + pCons(xs) + ")"
} 
Haskell
pCons :: [Int] -> String  
pCons [] = "nil"  
pCons (x:xs) = "(" ++ show x ++ "." ++ pCons xs ++ ")"  
ML
fun pCons [] = "nil"  
  | pCons (x::xs) = (concat ["(",(Int.toString x),".",(pCons xs),")"]);
OCaml
let rec p_cons = function  
  | []  -> "nil" 
  | x::xs -> "(" ^ string_of_int x ^ "." ^ p_cons xs ^ ")"

Language example

The other example defined a small language that contains 4 different types of expressions. Number, Sum, Product and Fun (function). Using this language, we can build different expressions.

Then we created 2 methods:

  • prn - Takes an expression as an argument, then prints it in a Clojure-like way.
  • calc - Takes an expression as an argument, which it then evaluates.

Both these methods are solved using recursive functions and pattern matching.

Defining the language

First, let's define the language using case classes for Scala, and datatypes for Haskell, ML and OCaml.

Scala
abstract class Exp

case class Number(n: Int) extends Exp  
case class Sum(e1: Exp, e2: Exp) extends Exp  
case class Product(e1: Exp, e2: Exp) extends Exp  
case class Fun(e: Exp) extends Exp  
Haskell
data Exp = Number Int  
         | Sum Exp Exp 
         | Product Exp Exp
         | Fun Exp
ML
datatype exp = Number of int  
             | Sum of exp * exp 
             | Product of exp * exp
             | Fun of exp;
OCaml
type exp = Number of int  
         | Sum of exp * exp 
         | Product of exp * exp 
         | Fun of exp

Print function

Next is the prn function, that prints a given expression in a Clojure-like way.

Scala
def prn(e: Exp): String = e match {  
    case Number(x) => x.toString
    case Sum(e1, e2) => "(+ " + prn(e1) + " " + prn(e2) + ")"
    case Product(e1, e2) => "(* " + prn(e1) + " " + prn(e2) + ")"
    case Fun(e) => "(fn [] " + prn(e) + ")"
}
Haskell
prn :: Exp -> String  
prn (Number x) = show x  
prn (Sum e1 e2) = "(+ " ++ prn e1 ++ " " ++ prn e2 ++ ")"  
prn (Product e1 e2) = "(* " ++ prn e1 ++ " " ++ prn e2 ++ ")"  
prn (Fun e) = "(fn [] " ++ prn e ++ ")"  
ML
fun prn (Number(x)) = (Int.toString x)  
  | prn (Sum(e1, e2)) = (concat ["(+ ", (prn e1), " ", (prn e2), ")"])
  | prn (Product(e1, e2)) = (concat ["(* ", (prn e1), " ", (prn e2), ")"])
  | prn (Fun(e)) = (concat ["(fn [] ", (prn e), ")"]);
OCaml
let rec prn = function  
  | Number(x)  -> string_of_int x
  | Sum(e1, e2) -> "(+ " ^ prn e1 ^ " " ^ prn e2 ^ ")"
  | Product(e1, e2) -> "(* " ^ prn e1 ^ " " ^ prn e2 ^ ")"
  | Fun(e) -> "(fn [] " ^ prn e ^ ")"

Calculate function

Last, is the calc function that evaluates the expression given as an argument.

Scala
def calc(e: Exp): Int = e match {  
    case Number(x) => x
    case Sum(e1, e2) => calc(e1) + calc(e2)
    case Product(e1, e2) => calc(e1) * calc(e2)
    case Fun(e) => calc(e)
Haskell
calc :: Exp -> Int  
calc (Number x) = x  
calc (Sum e1 e2) = calc e1 + calc e2  
calc (Product e1 e2) = calc e1 * calc e2  
calc (Fun e) = calc e  
ML
fun calc (Number(x)) = x  
  | calc (Sum(e1, e2)) = (calc e1) + (calc e2)
  | calc (Product(e1, e2)) = (calc e1) * (calc e2)
  | calc (Fun(e)) = (calc e);
OCaml
let rec calc = function  
  | Number(x)  -> x 
  | Sum(e1, e2) -> calc e1 + calc e2 
  | Product(e1, e2) -> calc e1 * calc e2 
  | Fun(e) -> calc e

Enjoyed the post?

If you don't want to miss future posts, make sure to subscribe