[Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Arnaud Bailly
Hello,
In a recent thread, it has been asserted that defining type class is
something you seldom need when programming in Haskell.

There is one thing that as non-professional Haskell programmer I found
type-classes useful for: Testing. This is probably very OO and is pretty
much influenced by what I read in RWH but I find useful to define TC that
abstract away from low-level interactions with other code, possibly IO
related, in such a way that I can have one implementation for testing and
one implementation for real work that is wired in caller context. This is
what is called mockist TDD in some circles: Write code that expresses what
it needs in its own terms, then implement glue to the code that provide
the concrete behaviour.

For example, while designing some program (a game...) I defined a type class
thus:

 class (Monad io) = CommandIO io where
  readCommand  :: io Command
  writeResult  :: CommandResult - io ()

Then I defined in a module Commands.IO :

 instance CommandIO IO where
  readCommand = do input - getLine
  ...
 writeResult r = putStrLn $ show r

and for the purpose of testing I defined in some test module:

 instance CommandIO (S.State ([Command],[CommandResult])) where
   readCommand   = do ((c:cs),rs) - S.get
 
   writeResult r = do (cs,rs) - S.get
 ...

Is this badly designed  code that tries to mimic OO in a functional setting?
If the answer is yes, how could I achieve same result (eg. testing the code
that does command REPL) without defining type classes?

Regards,
Arnaud
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Evan Laforge
 Is this badly designed  code that tries to mimic OO in a functional setting?
 If the answer is yes, how could I achieve same result (eg. testing the code
 that does command REPL) without defining type classes?

Here's how I do it:

data InteractiveState = InteractiveState {
  state_read :: IO Command
  , state_write :: Result - IO ()
  }

Now when I run it for real, I pass 'InteractiveState getLine putStrLn'
and when I run it for testing, I pass 'InteractiveState (getChan
in_chan) (putChan out_chan)'.

Of course, you have to pass this InteractiveState around, but
hopefully your IO using section is restricted to a small event loop
and threading it through is not a burden.  And there's always StateT.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Arnaud Bailly
On Tue, Jun 7, 2011 at 10:32 PM, Evan Laforge qdun...@gmail.com wrote:

  Is this badly designed  code that tries to mimic OO in a functional
 setting?
  If the answer is yes, how could I achieve same result (eg. testing the
 code
  that does command REPL) without defining type classes?

 Here's how I do it:

 data InteractiveState = InteractiveState {
  state_read :: IO Command
  , state_write :: Result - IO ()
  }


How about :

 data InteractiveState io = InteractiveState {
 state_read :: io Command
 , state_write :: Result - io ()
 }

Then you don't even depend on some specific monad. I understand you can
always (always?) encapsulate what is done through a type class by using a
data containing functions. But then, is this not even closer to OO
programming, an object that carries its own methods with itself, possibly
with the additional overhead that *each* instance would have its own private
references to possibly identical functions.

Thanks,
Arnaud
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Evan Laforge
 Here's how I do it:

 data InteractiveState = InteractiveState {
  state_read :: IO Command
  , state_write :: Result - IO ()
  }


 How about :

 data InteractiveState io = InteractiveState {
 state_read :: io Command
 , state_write :: Result - io ()
 }

I guess you could, but I like it concrete.

 Then you don't even depend on some specific monad. I understand you can
 always (always?) encapsulate what is done through a type class by using a
 data containing functions. But then, is this not even closer to OO
 programming, an object that carries its own methods with itself, possibly
 with the additional overhead that *each* instance would have its own private
 references to possibly identical functions.

No, because I don't think there are any objects?  In fact, I'm not
even sure what you mean.  I'm assuming you have an event loop like:

event_loop st = do
  cmd - state_read st
  state_write st (calculate_response cmd)
  event_loop st

calculate_response :: Command - Result

Since 'st' never changes (in my case it does have some changing
values), you can just write:

event_loop st = forever $ state_write st = calculate_response $
state_read st

There are no objects or private references here, and I'm not even sure
what they mean in this context.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Brandon Allbery
On Tue, Jun 7, 2011 at 16:16, Arnaud Bailly arnaud.oq...@gmail.com wrote:
 For example, while designing some program (a game...) I defined a type class
 thus:

 class (Monad io) = CommandIO io where
  readCommand  :: io Command
  writeResult  :: CommandResult - io ()

This is in fact one of the reasons to use type classes.  In fact,
you'll find a somewhat more general variety of it on Hackage in a
couple of forms, the one I'm most familiar with being MonadPrompt.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Yves Parès
 Is this badly designed  code that tries to mimic OO in a functional
setting? If the answer is yes, how could I achieve same result (eg. testing
the code that does command REPL) without defining type classes?

Why would that be badly designed? And why would that be more OO? IMO it is a
perfectly suited usage of type classes.

 Here's how I do it:

 data InteractiveState = InteractiveState {
  state_read :: IO Command
 , state_write :: Result - IO ()
 }

Well, it's pretty much the same thing, except you explicitely carry a value
containing your methods instead of simply carrying a type. Plus it delays
the resolution of which function will be called to the execution.
With typeclasses, it will be determined statically, no need to carry the
functions.


2011/6/7 Arnaud Bailly arnaud.oq...@gmail.com

 Hello,
 In a recent thread, it has been asserted that defining type class is
 something you seldom need when programming in Haskell.

 There is one thing that as non-professional Haskell programmer I found
 type-classes useful for: Testing. This is probably very OO and is pretty
 much influenced by what I read in RWH but I find useful to define TC that
 abstract away from low-level interactions with other code, possibly IO
 related, in such a way that I can have one implementation for testing and
 one implementation for real work that is wired in caller context. This is
 what is called mockist TDD in some circles: Write code that expresses what
 it needs in its own terms, then implement glue to the code that provide
 the concrete behaviour.

 For example, while designing some program (a game...) I defined a type
 class thus:

  class (Monad io) = CommandIO io where
   readCommand  :: io Command
   writeResult  :: CommandResult - io ()

 Then I defined in a module Commands.IO :

  instance CommandIO IO where
   readCommand = do input - getLine
   ...
  writeResult r = putStrLn $ show r

 and for the purpose of testing I defined in some test module:

  instance CommandIO (S.State ([Command],[CommandResult])) where
readCommand   = do ((c:cs),rs) - S.get
  
writeResult r = do (cs,rs) - S.get
  ...

 Is this badly designed  code that tries to mimic OO in a functional
 setting? If the answer is yes, how could I achieve same result (eg. testing
 the code that does command REPL) without defining type classes?

 Regards,
 Arnaud



 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Non-advanced usage of Type classes

2011-06-07 Thread Yves Parès
...and the other one being operational (which I find simpler).


2011/6/8 Brandon Allbery allber...@gmail.com

 On Tue, Jun 7, 2011 at 16:16, Arnaud Bailly arnaud.oq...@gmail.com
 wrote:
  For example, while designing some program (a game...) I defined a type
 class
  thus:
 
  class (Monad io) = CommandIO io where
   readCommand  :: io Command
   writeResult  :: CommandResult - io ()

 This is in fact one of the reasons to use type classes.  In fact,
 you'll find a somewhat more general variety of it on Hackage in a
 couple of forms, the one I'm most familiar with being MonadPrompt.

 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe