How would you write this code using Functional programming - oop

I am learning Object Oriented and Functional programming. I found this very good and brief example (if you know better example, please suggest) on youtube explaining the OOP in 10 minutes, yay!
https://www.youtube.com/watch?v=4c4nP7GLL1c
Now, I would like to learn how to write this code in a Functional way - with immutability, recursion no loops etc.
DEMO.PHP
<?php
Include_once(“player.php”);
$p1 = new player();
$p1->name = “Brutus”;
$p1->type = “Warrior”;
$p1->hitpoints = 100;
$p2 = new player();
$p2->name = “Mysterio”;
$p2->type = “Sorcerer”;
$p2->hitpoints = 100;
$p1->meleeAttack($p2);
$p2->meleeAttack($p1);
Echo “<h1> Fight Results</h1>”;
Echo “<h2>.$p1->name.” now has “.$p1->hitpoints.” hit points</h2>”;
Echo “<h2>.$p2->name.” now has “.$p2->hitpoints.” hit points</h2>”;
?>
PLAYER.PHP
<?php
Class player {
public $name;
public $type;
public $hitpoints;
public function meleeAttack($target){
$current_hp = $target->hitpoints; // hp is for hitpoints
$damage = rand(10,20);
if($this->type == “Warrior”) { // condition logic
$damage += 10;
}
$target->hitpoints = $current_hp - $damage;
}
}
?>
Cheers,
P.S. I know, PHP is not a language of choice for functional programming, no need to remind it :)

I'll explain how to do functional programming using Haskell because I don't know PHP:
import System.Random (randomRIO)
-- Data Declarations
data Class = Warrior | Sorcerer deriving Eq
data Player = Player { name :: String
, archetype :: Class
, hitpoints :: Int
}
-- Example Data
p1 :: Player
p1 = Player "Brutus" Warrior 100
p2 :: Player
p2 = Player "Mysterio" Sorcerer 100
-- Code Section
meleeAttack :: Player -> Player -> IO Player
source `meleeAttack` target = do
damage <- randomRIO (10, 20)
let bonus = if archetype source == Warrior then 10 else 0
let newHP = hitpoints target - damage - bonus
return target { hitpoints = newHP }
-- Main Function
main :: IO ()
main = do
p2 <- p1 `meleeAttack` p2
p1 <- p2 `meleeAttack` p1
putStrLn "Fight Results"
putStrLn (name p1 ++ " now has " ++ show (hitpoints p1) ++ " hitpoints")
putStrLn (name p2 ++ " now has " ++ show (hitpoints p2) ++ " hitpoints")
Alright, so one of the biggest differences between object oriented programming and functional programming is separation of code and data:
In object oriented programming code and data are not kept separate. Just look at your own Player class. It has three public fields and a public method that operates on those fields.
In functional programming code and data are kept separate. Our data declarations are at the beginning of the program and the functions operating on that data come afterwards.
Another big difference is mutability. In object oriented programming, objects are usually mutable. Hence, methods usually modify an existing object. In functional programming mutation is considered bad. Hence, functions usually never modify anything. Instead, they return an updated copy of whatever data they were manipulating.
For example, consider the meleeAttack function. It takes two inputs, source and target, which are both Player data. The output is also Player data. It's the updated target. The original target is left unmodified.
Anyway, if you want to learn functional programming then you should read Learn You A Haskell.

Related

How do you implement Object-Oriented polymorphism in a functional language?

Say you have this in an Object-Oriented application:
module Talker
def talk(word)
puts word
end
end
module Swimmer
def swim(distance)
puts "swimming #{distance}"
end
end
class Organism
def initialize
rise
end
def rise
puts "hello world"
end
end
class Animal extends Organism
def think(something)
puts "think #{something}"
end
end
class Bird extends Animal
include Talker
end
class Fish extends Animal
include Swimmer
end
bird = new Bird
fish = new Fish
In this, you can call methods which are unique to each:
bird.talk("hello")
fish.swim(50)
But you can also call methods which are the same:
bird.think("fly")
fish.think("swim")
If I have a function that takes an animal, I can call the think function:
def experience(animal)
animal.think("one")
animal.think("two")
animal.think("one")
end
In a pseudo functional language, you can do the same basically:
function experience(animal) {
think(animal)
think(animal)
think(animal)
}
But not really, you would have to check the type:
function think(genericObject) {
if (genericObject is Animal) {
animalThink(genericObject)
} else if (genericObject is SomethingElse) {
somethingElseThink(genericObject)
}
}
That is because, when implementing your "experience" function, you don't want just animals to experience, you want rocks and trees and other things to experience too, but their experience functions are different.
function experience(thing) {
move(thing)
move(thing)
move(thing)
}
function move(thing) {
case thing {
match Animal then animalMove(thing)
match Plant then plantMove(thing)
match Rock then rockMove(thing)
}
}
In this way, you can't have a cleanly reusable function, your function must know of the specific types it's going to receive somewhere down the line.
Is there any way to avoid this and make it more like OO polymorphism, in a functional language?
If so, at a high level, how does it work under the hood if this can be solved in a functional language?
Achieving polymorphism in functional programming
https://www.quora.com/How-is-polymorphism-used-in-functional-programming-languages
https://wiki.haskell.org/OOP_vs_type_classes
Functional programming languages have a variety of ways of achieving polymorphism. I'm going to contrast Java (the OOP language I know best) with Haskell (the functional language I know best).
Way 1: "parametric polymorphism"
With parametric polymorphism, you don't need to know anything at all about the underlying type. For example, if I have a singly-linked list with elements of type T, I actually don't need to know anything about type T in order to find the length of the list. I would just write something like
length :: forall a . [a] -> Integer
length [] = 0
length (x:xs) = 1 + length xs
in Haskell (obviously I'd want to use a better algorithm in practice, but you get the idea). Note that it doesn't matter what the type of the list elements is; the code for getting the length is the same. The first line is the "type signature". It says that for every type a, length will take a list of a and output an integer.
This can't be used for too much "serious polymorphism", but it's definitely a strong start. It corresponds roughly to Java's generics.
Way 2: typeclass-style polymorphism
Even something as benign as checking for equality actually requires polymorphism. Different types require different code for checking equality, and for some types (generally functions), checking equality is literally impossible because of the halting problem. Thus, we use "type classes".
Let's say I define a new type with 2 elements, Bob and Larry. In Haskell, this looks like
data VeggieTalesStars = Bob | Larry
I would like to be able to compare two elements of type VeggieTalesStars for equality. To do this, I would need to implement an Eq instance.
instance Eq VeggieTalesStars where
Bob == Bob = True
Larry == Larry = True
Bob == Larry = False
Larry == Bob = False
Note that the function (==) has the type signature
(==) :: forall b . Eq b => b -> b -> Bool
This means that for every type b, if b has an Eq instance, then (==) can take two arguments of type b and return a Bool.
It's probably not too difficult for you to guess that the not-equals function (/=) also has the type signature
(/=) :: forall b . Eq b => b -> b -> Bool
Because (/=) is defined by
x /= y = not (x == y)
When we call the (/=) function, the function will deploy the correct version of the (==) function based on the types of the arguments. If the arguments have different types, you won't be able to compare them using (/=).
Typeclass-style polymorphism allows you to do the following:
class Animal b where
think :: b -> String -> String
-- we provide the default implementation
think b string = "think " ++ string
data Fish = Fish
data Bird = Bird
instance Animal Fish where
instance Animal Bird where
Both Fish and Bird implement the "Animal" typeclass, so we can call the think function on both. That is,
>>> think Bird "thought"
"think thought"
>>> think Fish "thought"
"think thought"
This use case corresponds roughly to Java interfaces - types can implement as many type classes as they want. But type classes are far more powerful than interfaces.
Way 3: Functions
If your object only has one method, it may as well just be a function. This is a very common way to avoid inheritance hierarchies - deal with functions rather than inheritors of a 1-method base class.
One might therefore define
type Animal = String -> String
basicAnimal :: Animal
basicAnimal thought = "think " ++ thought
An "animal" is really just a way of taking one string and producing another. This would correspond to the Java code
class Animal {
public String think(String thought) {
return "think " + thought;
}
}
Let's say that in Java, we decided to implement a subclass of animal as follows:
class ThoughtfulPerson extends Animal {
private final String thought;
public ThoughtfulPerson(final String thought) {
this.thought = thought;
}
#Override
public String think(String thought) {
System.out.println("I normally think " + this.thought ", but I'm currently thinking" + thought + ".");
}
}
In Haskell, we would implement this as
thoughtfulPerson :: String -> Animal
thoughtfulPerson originalThought newThought = "I normally think " ++ originalThought ", but I'm currently thinking" ++ newThought ++ "."
The "dependency injection" of Java code is realised by Haskell's higher-order functions.
Way 4: composition over inheritance + functions
Suppose we have an abstract base class Thing with two methods:
abstract class Thing {
public abstract String name();
public abstract void makeLightBlink(int duration);
}
I'm using Java-style syntax, but hopefully it's not too confusing.
Fundamentally, the only way to use this abstract base class is by calling its two methods. Therefore, a Thing should actually be considered to be an ordered pair consisting of a string and a function.
In a functional language like Haskell, we would write
data Thing = Thing { name :: String, makeLightsBlink :: Int -> IO () }
In other words, a "Thing" consists of two parts: a name, which is a string, and a function makeLightsBlink, which takes an Int and outputs an "IO action". This is Haskell's way of dealing with IO - through the type system.
Instead of defining subclasses of Thing, Haskell would just have you define functions which output a Thing (or define Things themselves directly). So if in Java you might define
class ConcreteThing extends Thing {
#Override
public String name() {
return "ConcreteThing";
}
#Override
public void makeLightsBlink(int duration) {
for (int i = 0; i < duration; i++) {
System.out.println("Lights are blinking!");
}
}
}
In Haskell, you would instead define
concreteThing :: Thing
concreteThing = Thing { name = "ConcreteThing", makeLightsBlink = blinkFunction } where
blinkFunction duration = for_ [1..duration] . const $ putStrLn "Lights are blinking!"
No need to do anything fancy. You can implement any behaviour you want by using composition and functions.
Way 5 - avoid polymorphism entirely
This corresponds to the "open vs closed principle" in object oriented programming.
Some times, the correct thing to do is actually to avoid polymorphism entirely. For example, consider how one might implement a singly-linked list in Java.
abstract class List<T> {
public abstract bool is_empty();
public abstract T head();
public abstract List<T> tail();
public int length() {
return empty() ? 0 : 1 + tail().length();
}
}
class EmptyList<T> {
#Override
public bool is_empty() {
return true;
}
#Override
public T head() {
throw new IllegalArgumentException("can't take head of empty list");
}
#Override
public List<T> tail() {
throw new IllegalArgumentException("can't take tail of empty list");
}
}
class NonEmptyList<T> {
private final T head;
private final List<T> tail;
public NonEmptyList(T head, List<T> tail) {
this.head = head;
this.tail = tail;
}
#Override
public bool is_empty() {
return false;
}
#Override
public T head() {
return self.head;
}
#Override
public List<T> tail() {
return self.tail;
}
}
However, this is actually not a good model because you'd like there to only be two ways of constructing a list - the empty way, and the non-empty way. Haskell allows you to do this quite simply. The analogous Haskell code is
data List t = EmptyList | NonEmptyList t (List t)
empty :: List t -> Bool
empty EmptyList = True
empty (NonEmptyList t listT) = False
head :: List t -> t
head EmptyList = error "can't take head of empty list"
head (NonEmptyList t listT) = t
tail :: List t -> List t
tail EmptyList = error "can't take tail of empty list"
tail (NonEmptyList t listT) = listT
length list = if empty list then 0 else 1 + length (tail list)
Of course, in Haskell we try to avoid functions that are "partial" - we try to make sure that every function always returns a value. So you won't see many Haskellers actually using the "head" and "tail" functions for precisely this reason - they sometimes error out. You'd instead see length defined by
length EmptyList = 0
length (NonEmptyList t listT) = 1 + length listT
using pattern-matching.
This feature of functional programming languages is called "algebraic data types". It's incredibly useful.
Hopefully, I've convinced you that not only does functional programming allow you to implement many object-oriented design patterns, it can actually allow you to express the same ideas in much more succinct and obvious forms.
I have added some sugar to your example because it was difficult to justify an object centric implementation with your functions.
Note that I don't write a lot of Haskell but I think it's the right language to draw a comparison.
I don't recommend comparing pure OO languages and pure FP languages directly as it is a waste of time. If you pick up a FP language and learn how to think functionally you will not miss any OO feature.
-- We define and create data of type Fish and Bird
data Fish = Fish String
nemo = Fish "Nemo";
data Bird = Bird String
tweety = Bird "Tweety"
-- We define how they can be displayed with the function `show`
instance Show Fish where
show (Fish name) = name ++ " the fish"
instance Show Bird where
show (Bird name) = name ++ " the bird"
{- We define how animals can think with the function `think`.
Both Fish and Bird will be Animals.
Notice how `show` dispatches to the correct implementation.
We need to add to the type signature the constraint that
animals are showable in order to use `show`.
-}
class Show a => Animal a where
think :: a -> String -> String
think animal thought =
show animal ++ " is thinking about " ++ thought
instance Animal Fish
instance Animal Bird
-- Same thing for Swimmer, only with Fish
class Show s => Swimmer s where
swim :: s -> String -> String
swim swimmer length =
show swimmer ++ " is swimming " ++ length
instance Swimmer Fish
-- Same thing for Singer, only with Bird
class Show s => Singer s where
sing :: s -> String
sing singer = show singer ++ " is singing"
instance Singer Bird
{- We define a function which applies to any animal.
The compiler can figure out that it takes any type
of the class Animal because we are using `think`.
-}
goToCollege animal = think animal "quantum physics"
-- we're printing the values to the console
main = do
-- prints "Nemo the fish is thinking about quantum physics"
print $ goToCollege nemo
-- prints "Nemo the fish is swimming 4 meters"
print $ swim nemo "4 meters"
-- prints "Tweety the bird is thinking about quantum physics"
print $ goToCollege tweety
-- prints "Tweety the bird is singing"
print $ sing tweety
I was wondering what it would look like in Clojure. It's not as satisfying because defprotocol doesn't provide default implementations, but then again: are we not forcing a style upon a language which is not designed for it?
(defprotocol Show
(show [showable]))
(defprotocol Animal
(think [animal thought]))
(defn animal-think [animal thought]
(str (show animal) " is thinking about " thought))
(defprotocol Swimmer
(swim [swimmer length]))
(defprotocol Singer
(sing [singer]))
(defrecord Fish [name]
Show
(show [fish] (str (:name fish) " the fish"))
Animal
(think [a b] (animal-think a b))
Swimmer
(swim [swimmer length] (str (show swimmer) " is swimming " length)))
(defrecord Bird [name]
Show
(show [fish] (str (:name fish) " the bird"))
Animal
(think [a b] (animal-think a b))
Singer
(sing [singer] (str (show singer) " is singing")))
(defn goToCollege [animal]
(think animal "quantum physics"))
(def nemo (Fish. "Nemo"))
(def tweety (Bird. "Tweety"))
(println (goToCollege nemo))
(println (swim nemo "4 meters"))
(println (goToCollege tweety))
(println (sing tweety))
The problem is that what kind of polymorphism you want. If you just need some polymorphism on compile time, Haskell's typeclass is nearly perfect for most situations.
If you want to have polymorphism of run time(i.e. dynamically switch behaviors based on runtime type), this programming pattern is discouraged in many functional programming languages since with powerful generics and typeclasses, dynamic polymorphism is not always necessary.
In short, If the language support subtype, you can choose dynamic polymorphism while in a strict functional language without complete subtypes, you should always program in a functional way. Lastly, If you still want both(dynamic polymorphism and powerful typeclasses), you can try languages with traits like Scala or Rust.

Is there a language with higher order conditionals?

Sometimes, I have a control structure (if, for, ...), and depending on a condition I either want to use the control structure, or only execute the body. As a simple example, I can do the following in C, but it's pretty ugly:
#ifdef APPLY_FILTER
if (filter()) {
#endif
// do something
#ifdef APPLY_FILTER
}
#endif
Also it doesn't work if I only know apply_filter at runtime. Of course, in this case I can just change the code to:
if (apply_filter && filter())
but that doesn't work in the general case of arbitrary control structures. (I don't have a nice example at hand, but recently I had some code that would have benefited a lot from a feature like this.)
Is there any langugage where I can apply conditions to control structures, i.e. have higher-order conditionals? In pseudocode, the above example would be:
<if apply_filter>
if (filter()) {
// ...
}
Or a more complicated example, if a varable is set wrap code in a function and start it as a thread:
<if (run_on_thread)>
void thread() {
<endif>
for (int i = 0; i < 10; i++) {
printf("%d\n", i);
sleep(1);
}
<if (run_on_thread)>
}
start_thread(&thread);
<endif>
(Actually, in this example I could imagine it would even be useful to give the meta condition a name, to ensure that the top and bottom s are in sync.)
I could imagine something like this is a feature in LISP, right?
Any language with first-class functions can pull this off. In fact, your use of "higher-order" is telling; the necessary abstraction will indeed be a higher-order function. The idea is to write a function applyIf which takes a boolean (enabled/disabled), a control-flow operator (really, just a function), and a block of code (any value in the domain of the function); then, if the boolean is true, the operator/function is applied to the block/value, and otherwise the block/value is just run/returned. This will be a lot clearer in code.
In Haskell, for instance, this pattern would be, without an explicit applyIf, written as:
example1 = (if applyFilter then when someFilter else id) body
example2 = (if runOnThread then (void . forkIO) else id) . forM_ [1..10] $ \i ->
print i >> threadDelay 1000000 -- threadDelay takes microseconds
Here, id is just the identity function \x -> x; it always returns its argument. Thus, (if cond then f else id) x is the same as f x if cond == True, and is the same as id x otherwise; and of course, id x is the same as x.
Then you could factor this pattern out into our applyIf combinator:
applyIf :: Bool -> (a -> a) -> a -> a
applyIf True f x = f x
applyIf False _ x = x
-- Or, how I'd probably actually write it:
-- applyIf True = id
-- applyIf False = flip const
-- Note that `flip f a b = f b a` and `const a _ = a`, so
-- `flip const = \_ a -> a` returns its second argument.
example1' = applyIf applyFilter (when someFilter) body
example2' = applyIf runOnThread (void . forkIO) . forM_ [1..10] $ \i ->
print i >> threadDelay 1000000
And then, of course, if some particular use of applyIf was a common pattern in your application, you could abstract over it:
-- Runs its argument on a separate thread if the application is configured to
-- run on more than one thread.
possiblyThreaded action = do
multithreaded <- (> 1) . numberOfThreads <$> getConfig
applyIf multithreaded (void . forkIO) action
example2'' = possiblyThreaded . forM_ [1..10] $ \i ->
print i >> threadDelay 1000000
As mentioned above, Haskell is certainly not alone in being able to express this idea. For instance, here's a translation into Ruby, with the caveat that my Ruby is very rusty, so this is likely to be unidiomatic. (I welcome suggestions on how to improve it.)
def apply_if(use_function, f, &block)
use_function ? f.call(&block) : yield
end
def example1a
do_when = lambda { |&block| if some_filter then block.call() end }
apply_if(apply_filter, do_when) { puts "Hello, world!" }
end
def example2a
apply_if(run_on_thread, Thread.method(:new)) do
(1..10).each { |i| puts i; sleep 1 }
end
end
def possibly_threaded(&block)
apply_if(app_config.number_of_threads > 1, Thread.method(:new), &block)
end
def example2b
possibly_threaded do
(1..10).each { |i| puts i; sleep 1 }
end
end
The point is the same—we wrap up the maybe-do-this-thing logic in its own function, and then apply that to the relevant block of code.
Note that this function is actually more general than just working on code blocks (as the Haskell type signature expresses); you can also, for instance, write abs n = applyIf (n < 0) negate n to implement the absolute value function. The key is to realize that code blocks themselves can be abstracted over, so things like if statements and for loops can just be functions. And we already know how to compose functions!
Also, all of the code above compiles and/or runs, but you'll need some imports and definitions. For the Haskell examples, you'll need the impots
import Control.Applicative -- for (<$>)
import Control.Monad -- for when, void, and forM_
import Control.Concurrent -- for forkIO and threadDelay
along with some bogus definitions of applyFilter, someFilter, body, runOnThread, numberOfThreads, and getConfig:
applyFilter = False
someFilter = False
body = putStrLn "Hello, world!"
runOnThread = True
getConfig = return 4 :: IO Int
numberOfThreads = id
For the Ruby examples, you'll need no imports and the following analogous bogus definitions:
def apply_filter; false; end
def some_filter; false; end
def run_on_thread; true; end
class AppConfig
attr_accessor :number_of_threads
def initialize(n)
#number_of_threads = n
end
end
def app_config; AppConfig.new(4); end
Common Lisp does not let you redefine if. You can, however, invent your own control structure as a macro in Lisp and use that instead.

How can i rewrite or convert this C++ code to Haskell code

The c++ code which i wanted to rewrite or convert is:
class numberClass
{
private:
int value;
public:
int read()
{
return value;
}
void load(int x)
{
value = x;
}
void increment()
{
value= value +1;
}
};
int main()
{
numberClass num;
num.load(5);
int x=num.read();
cout<<x<<endl;
num.increment();
x=num.read();
cout<<x;
}
I do not know how to make any entity(like variable in C++) that can hold value throughout the program in haskell.
Please help.
Thanks
Basically, you can't. Values are immutable, and Haskell has no variables in the sense of boxes where you store values, like C++ and similar. You can do something similar using IORefs (which are boxes you can store values in), but it's almost always a wrong design to use them.
Haskell is a very different programming language, it's not a good idea to try to translate code from a language like C, C++, Java or so to Haskell. One has to view the tasks from different angles and approach it in a different way.
That being said:
module Main (main) where
import Data.IORef
main :: IO ()
main = do
num <- newIORef 5 :: IO (IORef Int)
x <- readIORef num
print x
modifyIORef num (+1)
x <- readIORef num
print x
Well, assuming that it's the wrapping, not the mutability, you can easily have a type that only allows constructing constant values and incrementation:
module Incr (Incr, incr, fromIncr, toIncr) where
newtype Incr a = Incr a deriving (Read, Show)
fromIncr :: Incr a -> a
fromIncr (Incr x) = x
incr :: (Enum a) => Incr a -> Incr a
incr (Incr x) = Incr (succ x)
toIncr :: a -> Incr a
toIncr = Incr
As Daniel pointed out, mutability is out of the question, but another purpose of your class is encapsulation, which this module provides just like the C++ class. Of course to a Haskell programmer, this module might not seem very useful, but perhaps you have use cases in mind, where you want to statically prevent library users from using regular addition or multiplication.
A direct translation of your code to haskell is rather stupid but of course possible (as shown in Daniel's answer).
Usually when you are working with state in haskell you might be able to work with the State Monad. As long as you are executing inside the State Monad you can query and update your state. If you want to be able to do some IO in addition (as in your example), you need to stack your State Monad on top of IO.
Using this approach your code might look like this:
import Control.Monad.State
import Prelude hiding(read)
increment = modify (+1)
load = put
read = get
normal :: StateT Int IO ()
normal = do
load 5
x <- read
lift (print x)
increment
x <- read
lift (print x)
main = evalStateT normal 0
But here you don't have an explicit type for your numberClass. If you want this there is a nice library on hackage that you could use: data-lenses.
Using lenses the code might be a little closer to your C++ version:
{-# LANGUAGE TemplateHaskell #-}
import Control.Monad.State(StateT,evalStateT,lift)
import Prelude hiding(read)
import Data.Lens.Lazy((~=),access,(%=))
import Data.Lens.Template(makeLenses)
data Number = Number {
_value :: Int
} deriving (Show)
$( makeLenses [''Number] )
increment = value %= succ
load x = value ~= x
read = access value
withLens :: StateT Number IO ()
withLens = do
load 5
x <- read
lift $ print x
increment
x <- read
lift $ print x
main = evalStateT withLens (Number 0)
Still not exactly your code...but well, it's haskell and not yet another OO-language.

OCaml structural typing and lists

I'm having trouble with lists in OCaml. I've read conflicting statements saying whether or not the lists can be modified at runtime. Can the cons operator be used at runtime?
Additionally, why is a doberman (see below) allowed to be in a list of chihuahuas? How would one go about adding another chihuahua onto the list (as attempted with the last line)?
class virtual dog =
object
method virtual bark : unit
end;;
class chihuahua =
object
inherit dog
method bark = Printf.printf "Yip!"
end;;
class doberman =
object
inherit dog
method bark = Printf.printf "Roar!"
end;;
let c1 = new chihuahua;;
let c2 = new chihuahua;;
let c3 = new chihuahua;;
let d1 = new doberman;;
let arrayOfDogs = [c1;c2;d1];;
arrayOfDogs :: c3;;
1) You can use the cons operator at runtime, it just returns a new list rather than mutating the input list.
2) Class types in OCaml use "structural" subtyping, rather than Java-style "nominal" subtyping. The inferred type of arrayOfDogs will be "an object with a method named bark of type unit -> unit (not necessarily a dog)". For example:
# class cat = object
method bark = print_endline "meow"
end ;;
class cat : object method bark : unit end
# let c = new cat ;;
val c : cat = <obj>
# c :: arrayOfDogs ;;
- : cat list = [<obj>; <obj>; <obj>; <obj>]
3) The problem with arrayOfDogs :: c3 is you've got it the wrong way around. The type of :: is 'a -> 'a list -> 'a list. To add c3 at the beginning, use
c3 :: arrayOfDogs
To add it at the end, use the "append" operator #
arrayOfDogs # [c3]
you need to have your list on the right hand side, not the left. Ie:
c3 :: arrayOfDogs;;
This is why the last line fails.
As far as the list construction goes, given that OCaml is type-inferred, the interpreter probably figured out that you're constructing a list of dogs given you added the doberman on construction. Therefore it's not a list of Chihuahuas.
What does OCaml report as the type of arrayOfDogs?
Perhaps you mean: c3 :: arrayOfDogs;;

Expression Evaluation and Tree Walking using polymorphism? (ala Steve Yegge)

This morning, I was reading Steve Yegge's: When Polymorphism Fails, when I came across a question that a co-worker of his used to ask potential employees when they came for their interview at Amazon.
As an example of polymorphism in
action, let's look at the classic
"eval" interview question, which (as
far as I know) was brought to Amazon
by Ron Braunstein. The question is
quite a rich one, as it manages to
probe a wide variety of important
skills: OOP design, recursion, binary
trees, polymorphism and runtime
typing, general coding skills, and (if
you want to make it extra hard)
parsing theory.
At some point, the candidate hopefully
realizes that you can represent an
arithmetic expression as a binary
tree, assuming you're only using
binary operators such as "+", "-",
"*", "/". The leaf nodes are all
numbers, and the internal nodes are
all operators. Evaluating the
expression means walking the tree. If
the candidate doesn't realize this,
you can gently lead them to it, or if
necessary, just tell them.
Even if you tell them, it's still an
interesting problem.
The first half of the question, which
some people (whose names I will
protect to my dying breath, but their
initials are Willie Lewis) feel is a
Job Requirement If You Want To Call
Yourself A Developer And Work At
Amazon, is actually kinda hard. The
question is: how do you go from an
arithmetic expression (e.g. in a
string) such as "2 + (2)" to an
expression tree. We may have an ADJ
challenge on this question at some
point.
The second half is: let's say this is
a 2-person project, and your partner,
who we'll call "Willie", is
responsible for transforming the
string expression into a tree. You get
the easy part: you need to decide what
classes Willie is to construct the
tree with. You can do it in any
language, but make sure you pick one,
or Willie will hand you assembly
language. If he's feeling ornery, it
will be for a processor that is no
longer manufactured in production.
You'd be amazed at how many candidates
boff this one.
I won't give away the answer, but a
Standard Bad Solution involves the use
of a switch or case statment (or just
good old-fashioned cascaded-ifs). A
Slightly Better Solution involves
using a table of function pointers,
and the Probably Best Solution
involves using polymorphism. I
encourage you to work through it
sometime. Fun stuff!
So, let's try to tackle the problem all three ways. How do you go from an arithmetic expression (e.g. in a string) such as "2 + (2)" to an expression tree using cascaded-if's, a table of function pointers, and/or polymorphism?
Feel free to tackle one, two, or all three.
[update: title modified to better match what most of the answers have been.]
Polymorphic Tree Walking, Python version
#!/usr/bin/python
class Node:
"""base class, you should not process one of these"""
def process(self):
raise('you should not be processing a node')
class BinaryNode(Node):
"""base class for binary nodes"""
def __init__(self, _left, _right):
self.left = _left
self.right = _right
def process(self):
raise('you should not be processing a binarynode')
class Plus(BinaryNode):
def process(self):
return self.left.process() + self.right.process()
class Minus(BinaryNode):
def process(self):
return self.left.process() - self.right.process()
class Mul(BinaryNode):
def process(self):
return self.left.process() * self.right.process()
class Div(BinaryNode):
def process(self):
return self.left.process() / self.right.process()
class Num(Node):
def __init__(self, _value):
self.value = _value
def process(self):
return self.value
def demo(n):
print n.process()
demo(Num(2)) # 2
demo(Plus(Num(2),Num(5))) # 2 + 3
demo(Plus(Mul(Num(2),Num(3)),Div(Num(10),Num(5)))) # (2 * 3) + (10 / 2)
The tests are just building up the binary trees by using constructors.
program structure:
abstract base class: Node
all Nodes inherit from this class
abstract base class: BinaryNode
all binary operators inherit from this class
process method does the work of evaluting the expression and returning the result
binary operator classes: Plus,Minus,Mul,Div
two child nodes, one each for left side and right side subexpressions
number class: Num
holds a leaf-node numeric value, e.g. 17 or 42
The problem, I think, is that we need to parse perentheses, and yet they are not a binary operator? Should we take (2) as a single token, that evaluates to 2?
The parens don't need to show up in the expression tree, but they do affect its shape. E.g., the tree for (1+2)+3 is different from 1+(2+3):
+
/ \
+ 3
/ \
1 2
versus
+
/ \
1 +
/ \
2 3
The parentheses are a "hint" to the parser (e.g., per superjoe30, to "recursively descend")
This gets into parsing/compiler theory, which is kind of a rabbit hole... The Dragon Book is the standard text for compiler construction, and takes this to extremes. In this particular case, you want to construct a context-free grammar for basic arithmetic, then use that grammar to parse out an abstract syntax tree. You can then iterate over the tree, reducing it from the bottom up (it's at this point you'd apply the polymorphism/function pointers/switch statement to reduce the tree).
I've found these notes to be incredibly helpful in compiler and parsing theory.
Representing the Nodes
If we want to include parentheses, we need 5 kinds of nodes:
the binary nodes: Add Minus Mul Divthese have two children, a left and right side
+
/ \
node node
a node to hold a value: Valno children nodes, just a numeric value
a node to keep track of the parens: Parena single child node for the subexpression
( )
|
node
For a polymorphic solution, we need to have this kind of class relationship:
Node
BinaryNode : inherit from Node
Plus : inherit from Binary Node
Minus : inherit from Binary Node
Mul : inherit from Binary Node
Div : inherit from Binary Node
Value : inherit from Node
Paren : inherit from node
There is a virtual function for all nodes called eval(). If you call that function, it will return the value of that subexpression.
String Tokenizer + LL(1) Parser will give you an expression tree... the polymorphism way might involve an abstract Arithmetic class with an "evaluate(a,b)" function, which is overridden for each of the operators involved (Addition, Subtraction etc) to return the appropriate value, and the tree contains Integers and Arithmetic operators, which can be evaluated by a post(?)-order traversal of the tree.
I won't give away the answer, but a
Standard Bad Solution involves the use
of a switch or case statment (or just
good old-fashioned cascaded-ifs). A
Slightly Better Solution involves
using a table of function pointers,
and the Probably Best Solution
involves using polymorphism.
The last twenty years of evolution in interpreters can be seen as going the other way - polymorphism (eg naive Smalltalk metacircular interpreters) to function pointers (naive lisp implementations, threaded code, C++) to switch (naive byte code interpreters), and then onwards to JITs and so on - which either require very big classes, or (in singly polymorphic languages) double-dispatch, which reduces the polymorphism to a type-case, and you're back at stage one. What definition of 'best' is in use here?
For simple stuff a polymorphic solution is OK - here's one I made earlier, but either stack and bytecode/switch or exploiting the runtime's compiler is usually better if you're, say, plotting a function with a few thousand data points.
Hm... I don't think you can write a top-down parser for this without backtracking, so it has to be some sort of a shift-reduce parser. LR(1) or even LALR will of course work just fine with the following (ad-hoc) language definition:
Start -> E1
E1 -> E1+E1 | E1-E1
E1 -> E2*E2 | E2/E2 | E2
E2 -> number | (E1)
Separating it out into E1 and E2 is necessary to maintain the precedence of * and / over + and -.
But this is how I would do it if I had to write the parser by hand:
Two stacks, one storing nodes of the tree as operands and one storing operators
Read the input left to right, make leaf nodes of the numbers and push them into the operand stack.
If you have >= 2 operands on the stack, pop 2, combine them with the topmost operator in the operator stack and push this structure back to the operand tree, unless
The next operator has higher precedence that the one currently on top of the stack.
This leaves us the problem of handling brackets. One elegant (I thought) solution is to store the precedence of each operator as a number in a variable. So initially,
int plus, minus = 1;
int mul, div = 2;
Now every time you see a a left bracket increment all these variables by 2, and every time you see a right bracket, decrement all the variables by 2.
This will ensure that the + in 3*(4+5) has higher precedence than the *, and 3*4 will not be pushed onto the stack. Instead it will wait for 5, push 4+5, then push 3*(4+5).
Re: Justin
I think the tree would look something like this:
+
/ \
2 ( )
|
2
Basically, you'd have an "eval" node, that just evaluates the tree below it. That would then be optimized out to just being:
+
/ \
2 2
In this case the parens aren't required and don't add anything. They don't add anything logically, so they'd just go away.
I think the question is about how to write a parser, not the evaluator. Or rather, how to create the expression tree from a string.
Case statements that return a base class don't exactly count.
The basic structure of a "polymorphic" solution (which is another way of saying, I don't care what you build this with, I just want to extend it with rewriting the least amount of code possible) is deserializing an object hierarchy from a stream with a (dynamic) set of known types.
The crux of the implementation of the polymorphic solution is to have a way to create an expression object from a pattern matcher, likely recursive. I.e., map a BNF or similar syntax to an object factory.
Or maybe this is the real question:
how can you represent (2) as a BST?
That is the part that is tripping me
up.
Recursion.
#Justin:
Look at my note on representing the nodes. If you use that scheme, then
2 + (2)
can be represented as
.
/ \
2 ( )
|
2
should use a functional language imo. Trees are harder to represent and manipulate in OO languages.
As people have been mentioning previously, when you use expression trees parens are not necessary. The order of operations becomes trivial and obvious when you're looking at an expression tree. The parens are hints to the parser.
While the accepted answer is the solution to one half of the problem, the other half - actually parsing the expression - is still unsolved. Typically, these sorts of problems can be solved using a recursive descent parser. Writing such a parser is often a fun exercise, but most modern tools for language parsing will abstract that away for you.
The parser is also significantly harder if you allow floating point numbers in your string. I had to create a DFA to accept floating point numbers in C -- it was a very painstaking and detailed task. Remember, valid floating points include: 10, 10., 10.123, 9.876e-5, 1.0f, .025, etc. I assume some dispensation from this (in favor of simplicty and brevity) was made in the interview.
I've written such a parser with some basic techniques like
Infix -> RPN and
Shunting Yard and
Tree Traversals.
Here is the implementation I've came up with.
It's written in C++ and compiles on both Linux and Windows.
Any suggestions/questions are welcomed.
So, let's try to tackle the problem all three ways. How do you go from an arithmetic expression (e.g. in a string) such as "2 + (2)" to an expression tree using cascaded-if's, a table of function pointers, and/or polymorphism?
This is interesting,but I don't think this belongs to the realm of object-oriented programming...I think it has more to do with parsing techniques.
I've kind of chucked this c# console app together as a bit of a proof of concept. Have a feeling it could be a lot better (that switch statement in GetNode is kind of clunky (it's there coz I hit a blank trying to map a class name to an operator)). Any suggestions on how it could be improved very welcome.
using System;
class Program
{
static void Main(string[] args)
{
string expression = "(((3.5 * 4.5) / (1 + 2)) + 5)";
Console.WriteLine(string.Format("{0} = {1}", expression, new Expression.ExpressionTree(expression).Value));
Console.WriteLine("\nShow's over folks, press a key to exit");
Console.ReadKey(false);
}
}
namespace Expression
{
// -------------------------------------------------------
abstract class NodeBase
{
public abstract double Value { get; }
}
// -------------------------------------------------------
class ValueNode : NodeBase
{
public ValueNode(double value)
{
_double = value;
}
private double _double;
public override double Value
{
get
{
return _double;
}
}
}
// -------------------------------------------------------
abstract class ExpressionNodeBase : NodeBase
{
protected NodeBase GetNode(string expression)
{
// Remove parenthesis
expression = RemoveParenthesis(expression);
// Is expression just a number?
double value = 0;
if (double.TryParse(expression, out value))
{
return new ValueNode(value);
}
else
{
int pos = ParseExpression(expression);
if (pos > 0)
{
string leftExpression = expression.Substring(0, pos - 1).Trim();
string rightExpression = expression.Substring(pos).Trim();
switch (expression.Substring(pos - 1, 1))
{
case "+":
return new Add(leftExpression, rightExpression);
case "-":
return new Subtract(leftExpression, rightExpression);
case "*":
return new Multiply(leftExpression, rightExpression);
case "/":
return new Divide(leftExpression, rightExpression);
default:
throw new Exception("Unknown operator");
}
}
else
{
throw new Exception("Unable to parse expression");
}
}
}
private string RemoveParenthesis(string expression)
{
if (expression.Contains("("))
{
expression = expression.Trim();
int level = 0;
int pos = 0;
foreach (char token in expression.ToCharArray())
{
pos++;
switch (token)
{
case '(':
level++;
break;
case ')':
level--;
break;
}
if (level == 0)
{
break;
}
}
if (level == 0 && pos == expression.Length)
{
expression = expression.Substring(1, expression.Length - 2);
expression = RemoveParenthesis(expression);
}
}
return expression;
}
private int ParseExpression(string expression)
{
int winningLevel = 0;
byte winningTokenWeight = 0;
int winningPos = 0;
int level = 0;
int pos = 0;
foreach (char token in expression.ToCharArray())
{
pos++;
switch (token)
{
case '(':
level++;
break;
case ')':
level--;
break;
}
if (level <= winningLevel)
{
if (OperatorWeight(token) > winningTokenWeight)
{
winningLevel = level;
winningTokenWeight = OperatorWeight(token);
winningPos = pos;
}
}
}
return winningPos;
}
private byte OperatorWeight(char value)
{
switch (value)
{
case '+':
case '-':
return 3;
case '*':
return 2;
case '/':
return 1;
default:
return 0;
}
}
}
// -------------------------------------------------------
class ExpressionTree : ExpressionNodeBase
{
protected NodeBase _rootNode;
public ExpressionTree(string expression)
{
_rootNode = GetNode(expression);
}
public override double Value
{
get
{
return _rootNode.Value;
}
}
}
// -------------------------------------------------------
abstract class OperatorNodeBase : ExpressionNodeBase
{
protected NodeBase _leftNode;
protected NodeBase _rightNode;
public OperatorNodeBase(string leftExpression, string rightExpression)
{
_leftNode = GetNode(leftExpression);
_rightNode = GetNode(rightExpression);
}
}
// -------------------------------------------------------
class Add : OperatorNodeBase
{
public Add(string leftExpression, string rightExpression)
: base(leftExpression, rightExpression)
{
}
public override double Value
{
get
{
return _leftNode.Value + _rightNode.Value;
}
}
}
// -------------------------------------------------------
class Subtract : OperatorNodeBase
{
public Subtract(string leftExpression, string rightExpression)
: base(leftExpression, rightExpression)
{
}
public override double Value
{
get
{
return _leftNode.Value - _rightNode.Value;
}
}
}
// -------------------------------------------------------
class Divide : OperatorNodeBase
{
public Divide(string leftExpression, string rightExpression)
: base(leftExpression, rightExpression)
{
}
public override double Value
{
get
{
return _leftNode.Value / _rightNode.Value;
}
}
}
// -------------------------------------------------------
class Multiply : OperatorNodeBase
{
public Multiply(string leftExpression, string rightExpression)
: base(leftExpression, rightExpression)
{
}
public override double Value
{
get
{
return _leftNode.Value * _rightNode.Value;
}
}
}
}
Ok, here is my naive implementation. Sorry, I did not feel to use objects for that one but it is easy to convert. I feel a bit like evil Willy (from Steve's story).
#!/usr/bin/env python
#tree structure [left argument, operator, right argument, priority level]
tree_root = [None, None, None, None]
#count of parethesis nesting
parenthesis_level = 0
#current node with empty right argument
current_node = tree_root
#indices in tree_root nodes Left, Operator, Right, PRiority
L, O, R, PR = 0, 1, 2, 3
#functions that realise operators
def sum(a, b):
return a + b
def diff(a, b):
return a - b
def mul(a, b):
return a * b
def div(a, b):
return a / b
#tree evaluator
def process_node(n):
try:
len(n)
except TypeError:
return n
left = process_node(n[L])
right = process_node(n[R])
return n[O](left, right)
#mapping operators to relevant functions
o2f = {'+': sum, '-': diff, '*': mul, '/': div, '(': None, ')': None}
#converts token to a node in tree
def convert_token(t):
global current_node, tree_root, parenthesis_level
if t == '(':
parenthesis_level += 2
return
if t == ')':
parenthesis_level -= 2
return
try: #assumption that we have just an integer
l = int(t)
except (ValueError, TypeError):
pass #if not, no problem
else:
if tree_root[L] is None: #if it is first number, put it on the left of root node
tree_root[L] = l
else: #put on the right of current_node
current_node[R] = l
return
priority = (1 if t in '+-' else 2) + parenthesis_level
#if tree_root does not have operator put it there
if tree_root[O] is None and t in o2f:
tree_root[O] = o2f[t]
tree_root[PR] = priority
return
#if new node has less or equals priority, put it on the top of tree
if tree_root[PR] >= priority:
temp = [tree_root, o2f[t], None, priority]
tree_root = current_node = temp
return
#starting from root search for a place with higher priority in hierarchy
current_node = tree_root
while type(current_node[R]) != type(1) and priority > current_node[R][PR]:
current_node = current_node[R]
#insert new node
temp = [current_node[R], o2f[t], None, priority]
current_node[R] = temp
current_node = temp
def parse(e):
token = ''
for c in e:
if c <= '9' and c >='0':
token += c
continue
if c == ' ':
if token != '':
convert_token(token)
token = ''
continue
if c in o2f:
if token != '':
convert_token(token)
convert_token(c)
token = ''
continue
print "Unrecognized character:", c
if token != '':
convert_token(token)
def main():
parse('(((3 * 4) / (1 + 2)) + 5)')
print tree_root
print process_node(tree_root)
if __name__ == '__main__':
main()