[Haskell-cafe] Re: Functional version of this OO snippet

Apfelmus, Heinrich apfelmus at quantentunnel.de
Fri Dec 5 10:20:24 EST 2008


Thomas Davie wrote:
> Andrew Wagner wrote:
> 
>> Hi all,
>> public interface IEngine {
>>  void foo();
>>  void bar(string bah);
>>  ...
>> }
>> public class Program {
>> public void Run(IEngine engine){
>>  while(true){
>>    string command = GetLine();
>>    if (command.startsWith("foo")){
>>      engine.foo();
>>    } else if (command.startsWith("bar")){
>>      engine.bar(command);
>>    ...
>>    else break;
>> }
>>
>> In other words, I want to provide the same UI across multiple
>> implementations of the engine that actually processes the commands.
> 
> class IEngine a where
>   foo :: a -> String
>   bar :: a -> String -> String

You don't even need a type class, a simple data type is enough.

  data Engine = Engine { foo :: IO (), bar :: String -> IO () }

  run e = processCommand e =<< getLine

  processCommand e c
    | "foo" `isPrefixOf` c = foo e   >> run e
    | "bar" `isPrefixOf` c = bar e c >> run e
    | otherwise            = return ()


This always works because all object methods expect a "self" argument.
In other words, all type class translations of OOP classes have the form

  class IFoo a where
     method1 :: a -> ...
     method2 :: a -> ...
     ...

See also

http://www.haskell.org/haskellwiki/Existential_type#Using_constructors_and_combinators


Regards,
H. Apfelmus



More information about the Haskell-Cafe mailing list