
Hi there, Do you have any idea why the following code is not valid? class Guess g where makeGuess :: g -> String instance Guess GuessLetter where makeGuess = ... instance Guess GuessWord where makeGuess = ... *-- | This function is nod valid * nextGuess :: Guess g => String -> g nextGuess = ... Thank you. -Haisheng

On Sun, Mar 18, 2012 at 02:23, Haisheng Wu
Hi there, Do you have any idea why the following code is not valid?
class Guess g where makeGuess :: g -> String
instance Guess GuessLetter where makeGuess = ...
instance Guess GuessWord where makeGuess = ...
*-- | This function is nod valid * nextGuess :: Guess g => String -> g nextGuess = ...
You are probably assuming that you get to decide within nextGuess what type it will return; in fact, the type it will return is set by its context when invoked, and your implementation must be prepared to return any Guess based on what the caller wants. Since nextGuess has no way to *get* at that context, and the typeclass has no method that can be used to produce a result based on the requested result type (as with e.g. Read), it's not clear to me that it can actually return anything (that is, the only possible result is _|_). Mantra: "Typeclasses are not OOP." Don't try to think of them as OOP, you will only get into trouble. -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

I'd guess the problem is because nextGuess isn't capable of producing any
instance of Guess. The type signature of a function isn't just to provide
callers information about a function like in most languages, it's also a
contract the function itself must abide by. In contrast it's common in an
OO language like Java to provide a more general return type like an
interface or superclass in the method declaration, and then to return a
more concrete type in the actual method. Haskell in contrast requires that
you be capable of returning *anything* that your functions type signature
claims it can. In your example, nextGuess must be capable of producing
*any* instance of nextGuess that a caller of the function requests. Put
another way, both of these must be valid:
nextGuess "example" :: GuessLetter
nextGuess "example" :: GuessWord
Typically this is accomplished by making a function like nextGuess part of
the class as in how Read does it:
class Read a where
read :: Read a => String -> a
By definition then, any instance of read must provide a read function
capable of producing something of that type. So, it seems obvious the
solution to your problem is to make nextGuess part of the Guess class.
Alternatively if that's not really what you're trying to accomplish the
type signature of nextGuess is probably wrong. If you provide more detail
on what you're attempting to do maybe someone on here can suggest another
way of accomplishing it.
-R. Kyle Murphy
--
Curiosity was framed, Ignorance killed the cat.
On Sun, Mar 18, 2012 at 02:23, Haisheng Wu
Hi there, Do you have any idea why the following code is not valid?
class Guess g where makeGuess :: g -> String
instance Guess GuessLetter where makeGuess = ...
instance Guess GuessWord where makeGuess = ...
*-- | This function is nod valid * nextGuess :: Guess g => String -> g nextGuess = ...
Thank you.
-Haisheng
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Thank you Kyle and Brandon!
I am actually re-implementing a toy solution which was done in JavaScript.
Turns out I can not make quite clear difference between typeclasses and OOP
thus I got this question.
I'm also aware making a class for nextGuess would be helpful and I'm still
working on.
PS: you might like to find the toy program at :
https://github.com/freizl/play-hangman-game
-Haisheng
On Sun, Mar 18, 2012 at 5:13 PM, Kyle Murphy
I'd guess the problem is because nextGuess isn't capable of producing any instance of Guess. The type signature of a function isn't just to provide callers information about a function like in most languages, it's also a contract the function itself must abide by. In contrast it's common in an OO language like Java to provide a more general return type like an interface or superclass in the method declaration, and then to return a more concrete type in the actual method. Haskell in contrast requires that you be capable of returning *anything* that your functions type signature claims it can. In your example, nextGuess must be capable of producing *any* instance of nextGuess that a caller of the function requests. Put another way, both of these must be valid:
nextGuess "example" :: GuessLetter nextGuess "example" :: GuessWord
Typically this is accomplished by making a function like nextGuess part of the class as in how Read does it:
class Read a where read :: Read a => String -> a
By definition then, any instance of read must provide a read function capable of producing something of that type. So, it seems obvious the solution to your problem is to make nextGuess part of the Guess class. Alternatively if that's not really what you're trying to accomplish the type signature of nextGuess is probably wrong. If you provide more detail on what you're attempting to do maybe someone on here can suggest another way of accomplishing it.
-R. Kyle Murphy -- Curiosity was framed, Ignorance killed the cat.
On Sun, Mar 18, 2012 at 02:23, Haisheng Wu
wrote: Hi there, Do you have any idea why the following code is not valid?
class Guess g where makeGuess :: g -> String
instance Guess GuessLetter where makeGuess = ...
instance Guess GuessWord where makeGuess = ...
*-- | This function is nod valid * nextGuess :: Guess g => String -> g nextGuess = ...
Thank you.
-Haisheng
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (3)
-
Brandon Allbery
-
Haisheng Wu
-
Kyle Murphy