# Goals

From these examples, I've been trying to extract a real problem which "Is a Cow an Animal?" is trying to solve.
Goal #1
implement the rules below, rejecting at runtime *any* malformed program.

As seen below, it's pretty easy.

Goal #2
try to enforce the rules at compile-time,

this can be

• quite easy (eg: ensuring one doesn't feed carrots with grass),
• quite hard (eg: ensuring one doesn't feed cows with carrots or dead_rabbits),
• or very hard (eg: ensuring meat can be eaten only once)

# Description of the World

• everything has some amount of energy
• there are animals: cow, rabbit, human
• there is food:
• vegetable: grass, carrot

general rules:

• animals can eat some food, their energy is raised by the food's energy amount
• animals can be slaughtered, the result is meat ; the energy of the meat is the same as the energy of the animal
• there should be a way to handle a list of animals and the energy of each animal

• slaughtered animals can't eat anymore nor be slaughtered again
• meat can be eaten only once
• whereas vegetable is innumerable and can be eaten more than once

animals' accepted food:

• a cow only eats grass
• a rabbit only eats carrots
• a human eats carrots and *any* meat
IMPORTANT: feeding a cow with something else than grass is a fatal error (same for feeding a human with grass...)

when slaughtered:

• a cow becomes beef

# Implementations

 Python 0/11 should_fails detected at compile-time Ruby 0/11 should_fails detected at compile-time Scheme 0/11 should_fails detected at compile-time C++ 5/11 should_fails detected at compile-time C++ with parametric class 7/11 should_fails detected at compile-time C++ with parametric class and diamond multiple-inheritance 8/11 should_fails detected at compile-time C++ with parametric class and eaters tied to the food 8/11 should_fails detected at compile-time OCaml 5/11 should_fails detected at compile-time OCaml with parametric class tentative 1/11 should_fails succeeds :-(, 7/11 should_fails detected at compile-time OCaml with parametric class and variants 8/11 should_fails detected at compile-time Prolog tentative 3/11 should_fails succeeds :-( and 0/11 detected at compile-time Haskell faking OO, no monad 5/11 should_fails detected at compile-time, but doesn't ensure previous elements are not used Haskell with phantom types (simple) 8/11 should_fails detected at compile-time, but doesn't ensure previous elements are not used Haskell with phantom types (with type hierarchy) 8/11 should_fails detected at compile-time, but doesn't ensure previous elements are not used Haskell with monads and phantom types 8/11 should_fails detected at compile-time Scala 11/11 should_fails detected at compile-time, but doesn't ensure previous elements are not used ATS (test code) 11/11 should_fails detected at compile-time Typescript 8/11 should_fails detected at compile-time Java 5/11 should_fails detected at compile-time Java with generics 8/11 should_fails detected at compile-time

# Test example

(using Python's syntax, see the various implementations for some other syntaxes)
```
grass    = new_grass(5)
carrot   = new_carrot(10)

a_rabbit      = new_rabbit(100)
a_cow         = new_cow(1000)
a_human       = new_human(300)
another_human = new_human(350)

for o in [ a_rabbit, a_cow, a_human ]:
print "%s -> %d" % (o.name, o.energy)

a_rabbit.eat(carrot)
a_cow.eat(grass)

a_beef = a_cow.slaughter()

a_human.eat(carrot)
a_human.eat(carrot)
a_human.eat(a_beef)

a_human.eat(another_human.slaughter())

if a_human.energy != 1785: raise "failed"
```
and here are some examples that should fail
```new_cow(10).slaughter().eat(grass) # meat (food) can't eat
new_cow(10).slaughter().slaughter() # meat (food) can't be slaughtered
carrot.eat(grass)      # vegetable (food) can't eat
carrot.slaughter()     # vegetable (food) can't be slaughtered

new_cow(10).eat(carrot) # cow do not eat carrot
new_cow(10).eat(new_cow(10).slaughter()) # cow do not eat beef
a_human.eat(new_cow(10)) # can't eat live animals
a_human.eat(grass)     # human do not eat grass
a_human.eat(a_beef)    # a_beef is already eaten
a_cow.eat(grass)       # a_cow is dead, it can't eat
a_cow.slaughter()      # a_cow is dead, it can't be slaughtered again
```

# Remarks

• the implementation should allow to add new meats which must be accepted by human

Pixel