Browse thread
[Caml-list] Is a Cow an Animal?
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | james woodyatt <jhw@w...> |
| Subject: | Re: [Caml-list] Is a Cow an Animal? |
On Wednesday, April 17, 2002, at 04:40 PM, Pixel wrote:
> Based on
> http://www.visviva.com/transframe/papers/covar.htm
> http://pauillac.inria.fr/~remy/work/virtual/virtual005.html
>
> I made
> http://merd.net/pixel/language-study/various/is-a-cow-an-animal/
> and especially
> http://merd.net/pixel/language-study/various/is-a-cow-an-
> animal/ocaml2.listing
>
> Please help with some pbs!
Your problem is an extension of the one documented by Didier Remy, and
it's very similar to one I faced with the Iox library I posted
recently. I suspect it's a really, really common problem.
I read the statement on your page, and took a swing at it. Wasn't too
difficult.
I borrowed a technique I learned here from Brian Rogoff that uses an
abstract type with a contravariant type parameter for passing the type
of energy a food object contains to an animal object that can eat it.
(I wish I were smart enough to know the name for this technique.)
I also used the functional style because the problem statement had some
language about ensuring that animals are never slaughtered twice. You
really can't do that at compile time in Caml, but you could pretty
easily modify the code I present below so that it raises Failure if the
'consume' method is called on the same meat object more than once, or if
an energy value is fed to more than one animal.
I think the code demonstrates more flexibility as I show it here.
(*======================= pixelworld.mli ======================*)
type -'diet energy
class ['diet] thing:
int ->
object
val energy: 'a energy
method energy: int
end
class type ['diet] food =
object('a)
inherit ['diet] thing
method consume: 'diet energy * 'a option
end
class type ['diet] vegetable = ['diet] food
class type ['diet] meat = ['diet] food
class grass: int -> [[ `E_cow ]] vegetable
class carrot: int -> [[ `E_rabbit | `E_human ]] vegetable
class type beef = [[ `E_human ]] meat
class type coney = [[ `E_human ]] meat
class type longpig = [[ `E_human ]] meat
class ['diet, 'eater] animal:
int ->
object('a)
inherit ['diet] thing
method feed: 'diet energy -> 'a
method slaughter: 'eater meat
end
class cow: int -> [[ `E_cow ], [ `E_human ]] animal
class rabbit: int -> [[ `E_rabbit ], [ `E_human ]] animal
class human: int -> [[ `E_human ], [ `E_human ]] animal
(* end of signature *)
(*======================= pixelworld.ml ======================*)
type 'diet energy = int
class ['diet] thing (e : int) =
object
val energy: 'diet energy = e
method energy: int = energy
end
class type ['diet] food =
object('a)
inherit ['diet] thing
method consume: 'diet energy * 'a option
end
class ['diet] vegetable e : ['diet] food =
object
inherit ['diet] thing e
method consume = energy, Some {< >}
end
class ['diet] meat e : ['diet] food =
object(_:'a)
inherit ['diet] thing e
method consume = energy, (None : 'a option)
end
class grass = [[ `E_cow ]] vegetable
class carrot = [[ `E_rabbit | `E_human ]] vegetable
class beef = [[ `E_human ]] meat
class coney = [[ `E_human ]] meat
class longpig = [[ `E_human ]] meat
class ['diet, 'eater] animal e =
object
inherit ['diet] thing e
method slaughter = ((new meat energy) : 'eater meat)
method feed (x : 'diet energy) = {< energy = energy + x >}
end
class cow = [[ `E_cow ], [ `E_human ]] animal
class rabbit = [[ `E_rabbit ], [ `E_human ]] animal
class human = [[ `E_human ], [ `E_human ]] animal
(* end of module *)
--
j h woodyatt <jhw@wetware.com>
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners