How to “extend” classes in HaskellGetting started with HaskellWhat is Haskell used for in the real world?Large-scale design in Haskell?Folding over a polymorphic list in HaskellGHC code generation for type class function callsHaskell: YesNo type class. Why Integer?Why not a more general function than mappend in Haskell?How is the instance of Show for String written?Haskell GADT typesafe Evaluator: Constant term for more than one type.Constraint on associated type in Haskell

How to duplicate all folders into same directory?

Does the House Resolution about the Impeachment Inquiry change anything?

Totally Blind Chess

Is the Night's Watch voting system based on history?

What are valid bugs

Dodging a Deathbeam travelling at speed of light

What is the hidden passcode?

If ancient soldiers could firebend, would battle lines cease to exist?

What is David Chalmers' Naturalistic dualism?

Beam slope indicating accelerando or rallentando

Can a sauce with dairy be jarred?

How does an ideal op amp amplify a voltage input when the voltage difference is 0?

Languages which changed their writing direction

Lvl20 Samurai+true strike=9 attacks all with advantage?

Can abstractions and good code practice in embedded C++ eliminate the need for the debugger?

How likely are you to be injured by falling shot from a game shoot?

Implement batch option --yes in bash script

Help with formulating an implication

How did Beit Shammai and Beit Hillel arrive at the conclusion that it would have been preferable had man not been created?

I have been accused of copying two lab report’s from the previous year even though I had done everything by myself

What does it mean by commercial support available in Open source platform?

Proving there exist three different vectors that sum to zero

Why does this Ultramarine have red armour?

How does an all-female medieval country maintain itself?



How to “extend” classes in Haskell


Getting started with HaskellWhat is Haskell used for in the real world?Large-scale design in Haskell?Folding over a polymorphic list in HaskellGHC code generation for type class function callsHaskell: YesNo type class. Why Integer?Why not a more general function than mappend in Haskell?How is the instance of Show for String written?Haskell GADT typesafe Evaluator: Constant term for more than one type.Constraint on associated type in Haskell






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









10

















I want to create two typeclasses, A and B, where A is a superclass of B. The functions defined in B are sufficient to implement those in A. Then, if I have a function with the constraint fun :: (A thing) => ... an instance of B for, say, Int, I'd like to be able to pass an Int to fun without creating a duplicate instance A for Int.



For example, let's say I have a type class which can check if value is "even". Then, I have another type class which can check if a value is divisible by some number. The second type class is powerful enough to implement the functions in the first, and any function which only requires "even-checking" capabilities should be able to accept an argument which has "divisible-by" abilities.



Here's what I think it would look like:



class IsEven a where
isEven :: a -> Bool

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool
isEven :: a -> Bool
isEven a = divisibleBy a 2

printIsEven :: (IsEven a) => a -> IO ()
printIsEven a = putStrLn (show (IsEven.isEven a))

instance IsEven Int -- I need to do this or I cannot create a DivisibleBy instance
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

myint :: Int
myint = 2

main :: IO ()
main = printIsEven myint


However, at compile time this produces the warning:



[2 of 2] Compiling Main ( Foo.hs, Foo.o )

Foo.hs:11:10: warning: [-Wmissing-methods]
• No explicit implementation for
‘IsEven.isEven’
• In the instance declaration for ‘IsEven Int’
|
11 | instance IsEven Int
| ^^^^^^^^^^
Linking Foo ...


and at runtime, the program fails:



Foo: Foo.hs:11:10-19: No instance nor default method for class operation isEven


How can I achieve this subtyping effect without duplicating logic into an instance IsEven?










share|improve this question























  • 3





    There is no reason for DivisibleBy to be a subclass of IsEven. The opposite relation is reasonable, as is making the two classes independent. Just because using divisibleBy is one way to define isEven doesn't mean an IsEven instance should be required.

    – chepner
    Jul 6 at 14:34

















10

















I want to create two typeclasses, A and B, where A is a superclass of B. The functions defined in B are sufficient to implement those in A. Then, if I have a function with the constraint fun :: (A thing) => ... an instance of B for, say, Int, I'd like to be able to pass an Int to fun without creating a duplicate instance A for Int.



For example, let's say I have a type class which can check if value is "even". Then, I have another type class which can check if a value is divisible by some number. The second type class is powerful enough to implement the functions in the first, and any function which only requires "even-checking" capabilities should be able to accept an argument which has "divisible-by" abilities.



Here's what I think it would look like:



class IsEven a where
isEven :: a -> Bool

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool
isEven :: a -> Bool
isEven a = divisibleBy a 2

printIsEven :: (IsEven a) => a -> IO ()
printIsEven a = putStrLn (show (IsEven.isEven a))

instance IsEven Int -- I need to do this or I cannot create a DivisibleBy instance
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

myint :: Int
myint = 2

main :: IO ()
main = printIsEven myint


However, at compile time this produces the warning:



[2 of 2] Compiling Main ( Foo.hs, Foo.o )

Foo.hs:11:10: warning: [-Wmissing-methods]
• No explicit implementation for
‘IsEven.isEven’
• In the instance declaration for ‘IsEven Int’
|
11 | instance IsEven Int
| ^^^^^^^^^^
Linking Foo ...


and at runtime, the program fails:



Foo: Foo.hs:11:10-19: No instance nor default method for class operation isEven


How can I achieve this subtyping effect without duplicating logic into an instance IsEven?










share|improve this question























  • 3





    There is no reason for DivisibleBy to be a subclass of IsEven. The opposite relation is reasonable, as is making the two classes independent. Just because using divisibleBy is one way to define isEven doesn't mean an IsEven instance should be required.

    – chepner
    Jul 6 at 14:34













10












10








10








I want to create two typeclasses, A and B, where A is a superclass of B. The functions defined in B are sufficient to implement those in A. Then, if I have a function with the constraint fun :: (A thing) => ... an instance of B for, say, Int, I'd like to be able to pass an Int to fun without creating a duplicate instance A for Int.



For example, let's say I have a type class which can check if value is "even". Then, I have another type class which can check if a value is divisible by some number. The second type class is powerful enough to implement the functions in the first, and any function which only requires "even-checking" capabilities should be able to accept an argument which has "divisible-by" abilities.



Here's what I think it would look like:



class IsEven a where
isEven :: a -> Bool

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool
isEven :: a -> Bool
isEven a = divisibleBy a 2

printIsEven :: (IsEven a) => a -> IO ()
printIsEven a = putStrLn (show (IsEven.isEven a))

instance IsEven Int -- I need to do this or I cannot create a DivisibleBy instance
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

myint :: Int
myint = 2

main :: IO ()
main = printIsEven myint


However, at compile time this produces the warning:



[2 of 2] Compiling Main ( Foo.hs, Foo.o )

Foo.hs:11:10: warning: [-Wmissing-methods]
• No explicit implementation for
‘IsEven.isEven’
• In the instance declaration for ‘IsEven Int’
|
11 | instance IsEven Int
| ^^^^^^^^^^
Linking Foo ...


and at runtime, the program fails:



Foo: Foo.hs:11:10-19: No instance nor default method for class operation isEven


How can I achieve this subtyping effect without duplicating logic into an instance IsEven?










share|improve this question

















I want to create two typeclasses, A and B, where A is a superclass of B. The functions defined in B are sufficient to implement those in A. Then, if I have a function with the constraint fun :: (A thing) => ... an instance of B for, say, Int, I'd like to be able to pass an Int to fun without creating a duplicate instance A for Int.



For example, let's say I have a type class which can check if value is "even". Then, I have another type class which can check if a value is divisible by some number. The second type class is powerful enough to implement the functions in the first, and any function which only requires "even-checking" capabilities should be able to accept an argument which has "divisible-by" abilities.



Here's what I think it would look like:



class IsEven a where
isEven :: a -> Bool

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool
isEven :: a -> Bool
isEven a = divisibleBy a 2

printIsEven :: (IsEven a) => a -> IO ()
printIsEven a = putStrLn (show (IsEven.isEven a))

instance IsEven Int -- I need to do this or I cannot create a DivisibleBy instance
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

myint :: Int
myint = 2

main :: IO ()
main = printIsEven myint


However, at compile time this produces the warning:



[2 of 2] Compiling Main ( Foo.hs, Foo.o )

Foo.hs:11:10: warning: [-Wmissing-methods]
• No explicit implementation for
‘IsEven.isEven’
• In the instance declaration for ‘IsEven Int’
|
11 | instance IsEven Int
| ^^^^^^^^^^
Linking Foo ...


and at runtime, the program fails:



Foo: Foo.hs:11:10-19: No instance nor default method for class operation isEven


How can I achieve this subtyping effect without duplicating logic into an instance IsEven?







haskell typeclass






share|improve this question
















share|improve this question













share|improve this question




share|improve this question








edited Jul 6 at 20:28









Peter Mortensen

14.6k19 gold badges89 silver badges118 bronze badges




14.6k19 gold badges89 silver badges118 bronze badges










asked Jul 6 at 4:52









David AbrahamsDavid Abrahams

765 bronze badges




765 bronze badges










  • 3





    There is no reason for DivisibleBy to be a subclass of IsEven. The opposite relation is reasonable, as is making the two classes independent. Just because using divisibleBy is one way to define isEven doesn't mean an IsEven instance should be required.

    – chepner
    Jul 6 at 14:34












  • 3





    There is no reason for DivisibleBy to be a subclass of IsEven. The opposite relation is reasonable, as is making the two classes independent. Just because using divisibleBy is one way to define isEven doesn't mean an IsEven instance should be required.

    – chepner
    Jul 6 at 14:34







3




3





There is no reason for DivisibleBy to be a subclass of IsEven. The opposite relation is reasonable, as is making the two classes independent. Just because using divisibleBy is one way to define isEven doesn't mean an IsEven instance should be required.

– chepner
Jul 6 at 14:34





There is no reason for DivisibleBy to be a subclass of IsEven. The opposite relation is reasonable, as is making the two classes independent. Just because using divisibleBy is one way to define isEven doesn't mean an IsEven instance should be required.

– chepner
Jul 6 at 14:34












3 Answers
3






active

oldest

votes


















13



















As far as I know, the closest you can get in standard Haskell is



instance IsEven Int where
isEven n = n `divisibleBy` 2

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


You don't have to duplicate the logic (indeed, you can implement isEven in terms of divisibleBy), but you still need to provide an explicit definition.



You would have to repeat this pattern for every type you want to make an instance of DivisibleBy.



Using the DefaultSignatures language extension you can also do the following:



-# LANGUAGE DefaultSignatures #-

class IsEven a where
isEven :: a -> Bool
default isEven :: (DivisibleBy a) => a -> Bool
isEven n = n `divisibleBy` 2

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool

instance IsEven Int
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


This moves the default implementation to the class itself. Now you can indeed just say instance IsEven Int without providing an instance body. The disadvantage is that now IsEven has to know about DivisibleBy, and you can only provide one default implementation.






share|improve this answer




























  • It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

    – duplode
    Jul 6 at 11:02



















7



















You can't redefine a method in a new class and have it affect the one in the old class. If you want methods to work like this, the parent class has to reference the child class.



You need the DefaultSignatures extension to make this work. Turn it on and then change your classes to this:



class IsEven a where
isEven :: a -> Bool
default isEven :: DivisibleBy a => a -> Bool
isEven a = divisibleBy a 2

class IsEven a => DivisibleBy a where
divisibleBy :: a -> Int -> Bool





share|improve this answer


























  • hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

    – David Abrahams
    Jul 6 at 5:09












  • @DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

    – Joseph Sible
    Jul 6 at 5:11


















5



















With GHC 8.6 and above, this can also be achieved through DerivingVia:



-# LANGUAGE DerivingVia #-
-# LANGUAGE GeneralisedNewtypeDeriving #-
-# LANGUAGE StandaloneDeriving #-

-- Class definitions:

class IsEven a where
isEven :: a -> Bool

-- Note that we don't need to have IsEven as a superclass.
class DivisibleBy a where
divisibleBy :: a -> Int -> Bool


-- Boilerplate that only needs to be written once:

-- Boilerplate DivisibleBy instance generated with GeneralisedNewtypeDeriving.
newtype WrappedDivisibleBy a = WrapDivisibleBy unwrapDivisibleBy :: a
deriving DivisibleBy

instance DivisibleBy a => IsEven (WrappedDivisibleBy a) where
isEven n = n `divisibleBy` 2


-- Instance example:

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

-- Boilerplate IsEven instance generated with DerivingVia
-- (and StandaloneDeriving, as we aren't defining Int here).
deriving via (WrappedDivisibleBy Int) instance IsEven Int


DerivingVia is not always an option (in the case of classes like Traversable, which have an extra type constructor wrapping things in the type signature, it clashes with the role system); when it works, though, it is very neat.






share|improve this answer




























  • Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

    – David Abrahams
    Jul 6 at 21:45






  • 1





    @DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

    – duplode
    Jul 6 at 21:53







  • 1





    I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

    – Iceland_jack
    Jul 9 at 14:29











  • @Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

    – duplode
    Jul 9 at 16:08







  • 1





    Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

    – Iceland_jack
    Jul 9 at 18:18













Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);














draft saved

draft discarded
















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56911322%2fhow-to-extend-classes-in-haskell%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown


























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









13



















As far as I know, the closest you can get in standard Haskell is



instance IsEven Int where
isEven n = n `divisibleBy` 2

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


You don't have to duplicate the logic (indeed, you can implement isEven in terms of divisibleBy), but you still need to provide an explicit definition.



You would have to repeat this pattern for every type you want to make an instance of DivisibleBy.



Using the DefaultSignatures language extension you can also do the following:



-# LANGUAGE DefaultSignatures #-

class IsEven a where
isEven :: a -> Bool
default isEven :: (DivisibleBy a) => a -> Bool
isEven n = n `divisibleBy` 2

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool

instance IsEven Int
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


This moves the default implementation to the class itself. Now you can indeed just say instance IsEven Int without providing an instance body. The disadvantage is that now IsEven has to know about DivisibleBy, and you can only provide one default implementation.






share|improve this answer




























  • It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

    – duplode
    Jul 6 at 11:02
















13



















As far as I know, the closest you can get in standard Haskell is



instance IsEven Int where
isEven n = n `divisibleBy` 2

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


You don't have to duplicate the logic (indeed, you can implement isEven in terms of divisibleBy), but you still need to provide an explicit definition.



You would have to repeat this pattern for every type you want to make an instance of DivisibleBy.



Using the DefaultSignatures language extension you can also do the following:



-# LANGUAGE DefaultSignatures #-

class IsEven a where
isEven :: a -> Bool
default isEven :: (DivisibleBy a) => a -> Bool
isEven n = n `divisibleBy` 2

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool

instance IsEven Int
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


This moves the default implementation to the class itself. Now you can indeed just say instance IsEven Int without providing an instance body. The disadvantage is that now IsEven has to know about DivisibleBy, and you can only provide one default implementation.






share|improve this answer




























  • It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

    – duplode
    Jul 6 at 11:02














13














13










13










As far as I know, the closest you can get in standard Haskell is



instance IsEven Int where
isEven n = n `divisibleBy` 2

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


You don't have to duplicate the logic (indeed, you can implement isEven in terms of divisibleBy), but you still need to provide an explicit definition.



You would have to repeat this pattern for every type you want to make an instance of DivisibleBy.



Using the DefaultSignatures language extension you can also do the following:



-# LANGUAGE DefaultSignatures #-

class IsEven a where
isEven :: a -> Bool
default isEven :: (DivisibleBy a) => a -> Bool
isEven n = n `divisibleBy` 2

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool

instance IsEven Int
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


This moves the default implementation to the class itself. Now you can indeed just say instance IsEven Int without providing an instance body. The disadvantage is that now IsEven has to know about DivisibleBy, and you can only provide one default implementation.






share|improve this answer
















As far as I know, the closest you can get in standard Haskell is



instance IsEven Int where
isEven n = n `divisibleBy` 2

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


You don't have to duplicate the logic (indeed, you can implement isEven in terms of divisibleBy), but you still need to provide an explicit definition.



You would have to repeat this pattern for every type you want to make an instance of DivisibleBy.



Using the DefaultSignatures language extension you can also do the following:



-# LANGUAGE DefaultSignatures #-

class IsEven a where
isEven :: a -> Bool
default isEven :: (DivisibleBy a) => a -> Bool
isEven n = n `divisibleBy` 2

class (IsEven a) => DivisibleBy a where
divisibleBy :: a -> Int -> Bool

instance IsEven Int
instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0


This moves the default implementation to the class itself. Now you can indeed just say instance IsEven Int without providing an instance body. The disadvantage is that now IsEven has to know about DivisibleBy, and you can only provide one default implementation.







share|improve this answer















share|improve this answer




share|improve this answer








edited Jul 6 at 5:16

























answered Jul 6 at 5:06









melpomenemelpomene

75k6 gold badges58 silver badges110 bronze badges




75k6 gold badges58 silver badges110 bronze badges















  • It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

    – duplode
    Jul 6 at 11:02


















  • It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

    – duplode
    Jul 6 at 11:02

















It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

– duplode
Jul 6 at 11:02






It might be worth it to explicitly note that the liftM idiom (in this case, defining isEvenDivisible :: DivisibleBy a => a -> Bool for the sake of writing boilerplate IsEven instances) might make the Haskell 98 solution slightly more comfortable. (Ultimately, I guess, it is a matter of how many extra names is one willing to tolerate, versus how often one can stand rewriting the full boilerplate implementation.)

– duplode
Jul 6 at 11:02














7



















You can't redefine a method in a new class and have it affect the one in the old class. If you want methods to work like this, the parent class has to reference the child class.



You need the DefaultSignatures extension to make this work. Turn it on and then change your classes to this:



class IsEven a where
isEven :: a -> Bool
default isEven :: DivisibleBy a => a -> Bool
isEven a = divisibleBy a 2

class IsEven a => DivisibleBy a where
divisibleBy :: a -> Int -> Bool





share|improve this answer


























  • hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

    – David Abrahams
    Jul 6 at 5:09












  • @DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

    – Joseph Sible
    Jul 6 at 5:11















7



















You can't redefine a method in a new class and have it affect the one in the old class. If you want methods to work like this, the parent class has to reference the child class.



You need the DefaultSignatures extension to make this work. Turn it on and then change your classes to this:



class IsEven a where
isEven :: a -> Bool
default isEven :: DivisibleBy a => a -> Bool
isEven a = divisibleBy a 2

class IsEven a => DivisibleBy a where
divisibleBy :: a -> Int -> Bool





share|improve this answer


























  • hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

    – David Abrahams
    Jul 6 at 5:09












  • @DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

    – Joseph Sible
    Jul 6 at 5:11













7














7










7










You can't redefine a method in a new class and have it affect the one in the old class. If you want methods to work like this, the parent class has to reference the child class.



You need the DefaultSignatures extension to make this work. Turn it on and then change your classes to this:



class IsEven a where
isEven :: a -> Bool
default isEven :: DivisibleBy a => a -> Bool
isEven a = divisibleBy a 2

class IsEven a => DivisibleBy a where
divisibleBy :: a -> Int -> Bool





share|improve this answer














You can't redefine a method in a new class and have it affect the one in the old class. If you want methods to work like this, the parent class has to reference the child class.



You need the DefaultSignatures extension to make this work. Turn it on and then change your classes to this:



class IsEven a where
isEven :: a -> Bool
default isEven :: DivisibleBy a => a -> Bool
isEven a = divisibleBy a 2

class IsEven a => DivisibleBy a where
divisibleBy :: a -> Int -> Bool






share|improve this answer













share|improve this answer




share|improve this answer










answered Jul 6 at 5:02









Joseph SibleJoseph Sible

14.7k3 gold badges20 silver badges52 bronze badges




14.7k3 gold badges20 silver badges52 bronze badges















  • hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

    – David Abrahams
    Jul 6 at 5:09












  • @DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

    – Joseph Sible
    Jul 6 at 5:11

















  • hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

    – David Abrahams
    Jul 6 at 5:09












  • @DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

    – Joseph Sible
    Jul 6 at 5:11
















hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

– David Abrahams
Jul 6 at 5:09






hm, but what if then there is some other type class which also has enough functionality to implement isEven? It seems like doing it this way requires the superclass to "know about" its subclass. In Scala, for example, you can subclass any typeclass and provide implementations for the superclasses methods. Eg, Applicative can implement Functor's map using ap: github.com/typelevel/cats/blob/master/core/src/main/scala/cats/… Is there a way to achieve something similar in Haskell? In Scala, if there is an Applicative in scope, you get a Functor for free.

– David Abrahams
Jul 6 at 5:09














@DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

– Joseph Sible
Jul 6 at 5:11





@DavidAbrahams I don't believe that Haskell currently has any equivalent to that functionality.

– Joseph Sible
Jul 6 at 5:11











5



















With GHC 8.6 and above, this can also be achieved through DerivingVia:



-# LANGUAGE DerivingVia #-
-# LANGUAGE GeneralisedNewtypeDeriving #-
-# LANGUAGE StandaloneDeriving #-

-- Class definitions:

class IsEven a where
isEven :: a -> Bool

-- Note that we don't need to have IsEven as a superclass.
class DivisibleBy a where
divisibleBy :: a -> Int -> Bool


-- Boilerplate that only needs to be written once:

-- Boilerplate DivisibleBy instance generated with GeneralisedNewtypeDeriving.
newtype WrappedDivisibleBy a = WrapDivisibleBy unwrapDivisibleBy :: a
deriving DivisibleBy

instance DivisibleBy a => IsEven (WrappedDivisibleBy a) where
isEven n = n `divisibleBy` 2


-- Instance example:

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

-- Boilerplate IsEven instance generated with DerivingVia
-- (and StandaloneDeriving, as we aren't defining Int here).
deriving via (WrappedDivisibleBy Int) instance IsEven Int


DerivingVia is not always an option (in the case of classes like Traversable, which have an extra type constructor wrapping things in the type signature, it clashes with the role system); when it works, though, it is very neat.






share|improve this answer




























  • Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

    – David Abrahams
    Jul 6 at 21:45






  • 1





    @DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

    – duplode
    Jul 6 at 21:53







  • 1





    I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

    – Iceland_jack
    Jul 9 at 14:29











  • @Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

    – duplode
    Jul 9 at 16:08







  • 1





    Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

    – Iceland_jack
    Jul 9 at 18:18
















5



















With GHC 8.6 and above, this can also be achieved through DerivingVia:



-# LANGUAGE DerivingVia #-
-# LANGUAGE GeneralisedNewtypeDeriving #-
-# LANGUAGE StandaloneDeriving #-

-- Class definitions:

class IsEven a where
isEven :: a -> Bool

-- Note that we don't need to have IsEven as a superclass.
class DivisibleBy a where
divisibleBy :: a -> Int -> Bool


-- Boilerplate that only needs to be written once:

-- Boilerplate DivisibleBy instance generated with GeneralisedNewtypeDeriving.
newtype WrappedDivisibleBy a = WrapDivisibleBy unwrapDivisibleBy :: a
deriving DivisibleBy

instance DivisibleBy a => IsEven (WrappedDivisibleBy a) where
isEven n = n `divisibleBy` 2


-- Instance example:

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

-- Boilerplate IsEven instance generated with DerivingVia
-- (and StandaloneDeriving, as we aren't defining Int here).
deriving via (WrappedDivisibleBy Int) instance IsEven Int


DerivingVia is not always an option (in the case of classes like Traversable, which have an extra type constructor wrapping things in the type signature, it clashes with the role system); when it works, though, it is very neat.






share|improve this answer




























  • Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

    – David Abrahams
    Jul 6 at 21:45






  • 1





    @DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

    – duplode
    Jul 6 at 21:53







  • 1





    I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

    – Iceland_jack
    Jul 9 at 14:29











  • @Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

    – duplode
    Jul 9 at 16:08







  • 1





    Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

    – Iceland_jack
    Jul 9 at 18:18














5














5










5










With GHC 8.6 and above, this can also be achieved through DerivingVia:



-# LANGUAGE DerivingVia #-
-# LANGUAGE GeneralisedNewtypeDeriving #-
-# LANGUAGE StandaloneDeriving #-

-- Class definitions:

class IsEven a where
isEven :: a -> Bool

-- Note that we don't need to have IsEven as a superclass.
class DivisibleBy a where
divisibleBy :: a -> Int -> Bool


-- Boilerplate that only needs to be written once:

-- Boilerplate DivisibleBy instance generated with GeneralisedNewtypeDeriving.
newtype WrappedDivisibleBy a = WrapDivisibleBy unwrapDivisibleBy :: a
deriving DivisibleBy

instance DivisibleBy a => IsEven (WrappedDivisibleBy a) where
isEven n = n `divisibleBy` 2


-- Instance example:

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

-- Boilerplate IsEven instance generated with DerivingVia
-- (and StandaloneDeriving, as we aren't defining Int here).
deriving via (WrappedDivisibleBy Int) instance IsEven Int


DerivingVia is not always an option (in the case of classes like Traversable, which have an extra type constructor wrapping things in the type signature, it clashes with the role system); when it works, though, it is very neat.






share|improve this answer
















With GHC 8.6 and above, this can also be achieved through DerivingVia:



-# LANGUAGE DerivingVia #-
-# LANGUAGE GeneralisedNewtypeDeriving #-
-# LANGUAGE StandaloneDeriving #-

-- Class definitions:

class IsEven a where
isEven :: a -> Bool

-- Note that we don't need to have IsEven as a superclass.
class DivisibleBy a where
divisibleBy :: a -> Int -> Bool


-- Boilerplate that only needs to be written once:

-- Boilerplate DivisibleBy instance generated with GeneralisedNewtypeDeriving.
newtype WrappedDivisibleBy a = WrapDivisibleBy unwrapDivisibleBy :: a
deriving DivisibleBy

instance DivisibleBy a => IsEven (WrappedDivisibleBy a) where
isEven n = n `divisibleBy` 2


-- Instance example:

instance DivisibleBy Int where
divisibleBy a i = a `mod` i == 0

-- Boilerplate IsEven instance generated with DerivingVia
-- (and StandaloneDeriving, as we aren't defining Int here).
deriving via (WrappedDivisibleBy Int) instance IsEven Int


DerivingVia is not always an option (in the case of classes like Traversable, which have an extra type constructor wrapping things in the type signature, it clashes with the role system); when it works, though, it is very neat.







share|improve this answer















share|improve this answer




share|improve this answer








edited Jul 6 at 21:54

























answered Jul 6 at 11:30









duplodeduplode

27.2k6 gold badges59 silver badges108 bronze badges




27.2k6 gold badges59 silver badges108 bronze badges















  • Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

    – David Abrahams
    Jul 6 at 21:45






  • 1





    @DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

    – duplode
    Jul 6 at 21:53







  • 1





    I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

    – Iceland_jack
    Jul 9 at 14:29











  • @Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

    – duplode
    Jul 9 at 16:08







  • 1





    Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

    – Iceland_jack
    Jul 9 at 18:18


















  • Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

    – David Abrahams
    Jul 6 at 21:45






  • 1





    @DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

    – duplode
    Jul 6 at 21:53







  • 1





    I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

    – Iceland_jack
    Jul 9 at 14:29











  • @Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

    – duplode
    Jul 9 at 16:08







  • 1





    Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

    – Iceland_jack
    Jul 9 at 18:18

















Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

– David Abrahams
Jul 6 at 21:45





Ah this is neat! I actually don't think we need DivisibleBy to extend isEven in this case, correct? (It compiles without it)

– David Abrahams
Jul 6 at 21:45




1




1





@DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

– duplode
Jul 6 at 21:53






@DavidAbrahams We don't, indeed. I have updated the answer to reflect that. (While here I'm primarily dealing with the typeclass mechanics, chepner does have a point about this specific example, so dropping the relationship looks like a net gain as far as this answer is concerned.)

– duplode
Jul 6 at 21:53





1




1





I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

– Iceland_jack
Jul 9 at 14:29





I always wanted unsafe via to bypass the role system, it would use unsafeCoerce instead of coerce

– Iceland_jack
Jul 9 at 14:29













@Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

– duplode
Jul 9 at 16:08






@Iceland_jack Tangential question: will the QuantifiedConstraints approach discussed in this ticket allow deriving Traversable and Distributive? Though I might well be reading the situation wrongly, it looks like that would demand coercing under an arbitrary functor that the instance implementer has no control over.

– duplode
Jul 9 at 16:08





1




1





Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

– Iceland_jack
Jul 9 at 18:18






Not as smoothly as join, requires big changes but I think it is the best path forward, the forall f a b. Applicative f => quantification appears in the type of traverse @t @f @a.., we can only work with t. Either strengthen Applicative f with Representational1 or decree all Functors be representational in their first arg by making class Representational1 f => Functor f a superclass. Ryan explains better: QuantifiedConstraints and the trouble with Traversable.

– Iceland_jack
Jul 9 at 18:18



















draft saved

draft discarded















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56911322%2fhow-to-extend-classes-in-haskell%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown









Popular posts from this blog

Tamil (spriik) Luke uk diar | Nawigatjuun

Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

Training a classifier when some of the features are unknownWhy does Gradient Boosting regression predict negative values when there are no negative y-values in my training set?How to improve an existing (trained) classifier?What is effect when I set up some self defined predisctor variables?Why Matlab neural network classification returns decimal values on prediction dataset?Fitting and transforming text data in training, testing, and validation setsHow to quantify the performance of the classifier (multi-class SVM) using the test data?How do I control for some patients providing multiple samples in my training data?Training and Test setTraining a convolutional neural network for image denoising in MatlabShouldn't an autoencoder with #(neurons in hidden layer) = #(neurons in input layer) be “perfect”?