If you desire to use toString :: a -> String
, I think you're simply forgetting about show :: a -> String
, or more properly Show a => show :: a -> String
.
If you want to operate on a type both having a :: a -> String
and :: String -> a
, you can simply put those type-class constraints on the functions.
doubleConstraintedFunction :: Show a, IsString a => a -> .. -> .. -> a
We carefully note that we avoid defining type classes having a set of functions that can as well be split into two subclasses. Therefor we don't put toString
in IsString
.
Finally, I must also mention about Read
, which provides Read a => String -> a
. You use read
and show
for very simple serialization. fromString
from IsString
has a different purpose, it's useful with the language pragma OverloadedStrings
, then you can very conveniently insert code like "This is not a string" :: Text
. (Text
is a (efficient) data-structure for Strings)