Martin Sulzmann
Comparing Rust and Haskell:
Data types and pattern matching (enum versus data)
Traits versus type classes
pub enum Exp {
Int {
val: i32
},
Plus {
left: Box<Exp>,
right: Box<Exp>
},
Mult{
left: Box<Exp>,
right: Box<Exp>
},
}
Box
required
Otherwise, recursive definition (without indirection)
fn eval(e : &Exp) -> i32 {
match e {
Exp::Int { val } => return *val,
Exp::Plus { left, right } => return eval(left) + eval(right),
Exp::Mult { left, right } => return eval(left) * eval(right),
}
}
fn example12() {
{
let e = Exp::Int { val : 1 };
println!("{}", eval(&e));
}
{
let e = Exp::Plus{left : Box::new(Exp::Int { val : 1 }), right : Box::new(Exp::Int { val : 2})};
println!("{}", eval(&e));
}
}
Automatic garbage collection
No need for pointers
eval :: Exp -> Int
eval (Val x) = x
eval (Plus l r) = eval l + eval r
eval (Mult l r) = eval l * eval r
struct Rectangle {
x : i32,
y : i32
}
struct Square {
x : i32
}
impl Shape for Rectangle {
fn area(r : &Rectangle) -> i32 {
return r.x * r.y;
}
}
impl Shape for Square {
fn area(s : &Square) -> i32 {
return s.x * s.x;
}
}
fn sum_area<A:Shape,B:Shape>(x : &A, y : &B) -> i32 {
return Shape::area(x) + Shape::area(y);
}
fn example_trait() {
let r = Rectangle{x : 1, y : 2};
let s = Square{x : 3};
println!("{}",sum_area(&r,&s));
}
data Square = MkSquare Int
data Rectangle = MkRectangle Int Int
instance Shape Square where
area (MkSquare x) = x * x
instance Shape Rectangle where
area (MkRectangle x y) = x * y
dyn
fn sum_area3(x : Box<dyn Shape2>, y : Box<dyn Shape2>) -> i32 {
return x.area2() + y.area2();
}
fn example_trait3() {
let r = Box::new(Rectangle{x : 1, y : 2});
let s = Box::new(Square{x : 3});
println!("{}",sum_area3(r,s));
}
//////////////////////////
// Traits
struct Rectangle {
x : i32,
y : i32
}
struct Square {
x : i32
}
trait Shape {
fn area(s : &Self) -> i32;
}
impl Shape for Rectangle {
fn area(r : &Rectangle) -> i32 {
return r.x * r.y;
}
}
impl Shape for Square {
fn area(s : &Square) -> i32 {
return s.x * s.x;
}
}
fn sum_area<A:Shape,B:Shape>(x : &A, y : &B) -> i32 {
return Shape::area(x) + Shape::area(y);
}
fn example_trait() {
let r = Rectangle{x : 1, y : 2};
let s = Square{x : 3};
println!("{}",sum_area(&r,&s));
}
// Method notation known from OO.
trait Shape2 {
fn area2(&self) -> i32;
}
impl Shape2 for Rectangle {
fn area2(&self) -> i32 {
return self.x * self.y;
}
}
impl Shape2 for Square {
fn area2(&self) -> i32 {
return self.x * self.x;
}
}
fn sum_area2<A:Shape2,B:Shape2>(x : &A, y : &B) -> i32 {
return x.area2() + y.area2();
}
fn example_trait2() {
let r = Rectangle{x : 1, y : 2};
let s = Square{x : 3};
println!("{}",sum_area2(&r,&s));
}
fn sum_area3(x : Box<dyn Shape2>, y : Box<dyn Shape2>) -> i32 {
return x.area2() + y.area2();
}
fn example_trait3() {
let r = Box::new(Rectangle{x : 1, y : 2});
let s = Box::new(Square{x : 3});
println!("{}",sum_area3(r,s));
}
////////////////////////////////////////////////
// Data types and pattern matching in Rust
pub enum Exp {
Int {
val: i32
},
Plus {
left: Box<Exp>,
right: Box<Exp>
},
Mult{
left: Box<Exp>,
right: Box<Exp>
},
}
fn eval(e : &Exp) -> i32 {
match e {
Exp::Int { val } => return *val,
Exp::Plus { left, right } => return eval(left) + eval(right),
Exp::Mult { left, right } => return eval(left) * eval(right),
}
}
fn example_data() {
{
let e = Exp::Int { val : 1 };
println!("{}", eval(&e));
}
{
let e = Exp::Plus{left : Box::new(Exp::Int { val : 1 }), right : Box::new(Exp::Int { val : 2})};
println!("{}", eval(&e));
}
}
fn main() {
example_trait();
example_trait2();
example_trait3();
example_data();
}
{-# LANGUAGE ExistentialQuantification #-}
-- Type classes
data Square = MkSquare Int
data Rectangle = MkRectangle Int Int
class Shape a where
area :: a -> Int
instance Shape Square where
area (MkSquare x) = x * x
instance Shape Rectangle where
area (MkRectangle x y) = x * y
sumArea :: (Shape a, Shape b) => a -> b -> Int
sumArea x y = area x + area y
exampleTrait =
let r = MkRectangle 1 2
s = MkSquare 3
in putStrLn (show $ sumArea r s)
-- Existential types
data DynShape = forall a. Shape a => MkDynShape a
sumArea3 :: DynShape -> DynShape -> Int
sumArea3 (MkDynShape x) (MkDynShape y) = area x + area y
exampleTrait3 =
let s1 = MkDynShape $ MkRectangle 1 2
s2 = MkDynShape $ MkSquare 3
in putStrLn (show $ sumArea3 s1 s2)
-- Pattern matching
data Exp = Val Int | Plus Exp Exp | Mult Exp Exp
eval :: Exp -> Int
eval (Val x) = x
eval (Plus l r) = eval l + eval r
eval (Mult l r) = eval l * eval r
exampleData =
let e = Plus (Val 1) (Val 2)
in putStrLn (show $ eval e)