[Haskell-cafe] Non-advanced usage of Type classes
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
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
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
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
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
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
...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