I am beginning with Haskell. I have a situation where it is convenient to work the following type synonyms:
type Adult = Int
type Youth = Int
However I can not overload functions on Adult
and Youth
even if they had been synonyms for different types so have to have two seperate versions of functions eg. doSomethingForAdult
and doSomethingForYouth
, so next I tried
data Person = Adult Int | Youth Int
Then I can pattern match and use a single version of functions,
but then I loose the option of using the Adult
and Youth
as types in functions declarations which is convenient. Is there a middle way ? I looked at Either
, but from the description in tutorials it seems this would be misuse ? Something similar to a small type hierarchy with Person
at the root and Youth
and Adult
derived and still being synonyms for Int
would be perfect but I can not figure out how.
I don't see how that would be a misuse of Either
. Just as (,)
is a generic product type, Either
is perfectly acceptable as a generic sum type, i.e. anything of the form:
data T = T1 A | T2 B C
...can be thought of algebraically as A + (B * C)
, which is equivalent to Either A (B, C)
.
On the other hand, if you want to distinguish between Adult
and Youth
, using synonyms for the same actual type can be counterproductive; they're just transparent aliases. An alternate approach would be to use newtype
s, like this:
newtype Adult = Adult Int deriving (Eq, Ord, Show, Read, Num)
newtype Youth = Youth Int deriving (Eq, Ord, Show, Read, Num)
Adjust the deriving
clause to taste; I added Num
here because the underlying type is numeric, but if all you want is a unique identifier then adding or multiplying them doesn't make sense. At this point you can then use a sum type for Person
if you like, or define a type class to get proper overloading:
class Person a where
-- (etc...)
instance Person Adult where -- ...
instance Person Youth where -- ...
Any functions defined in Person
are then effectively overloaded on Adult
and Youth
, letting you dispatch based on type the way "overloaded" functions in other languages do.
Are you wanting a typeclass
?
data Adult = Adult Int
data Youth = Youth Int
class Person a where
doSomething :: a -> b
instance Person Adult where
doSomething (Adult i) = ...
instance Person Youth where
doSomething (Youth i) = ...
This is the typical manner of overloading function in Haskell. The typeclass, Person
, has a single function, doSomething :: a -> b
. Each data type you want to be an instance of Person
can have its own, separate, implementation. If you want the underlying implementation to be the same then just use another function, doSomethingGlobal :: Int -> b
and let each instance equal this new function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With