Haskell中如何通过GHC扩展自动推导带默认实现的Bar IO实例?
FlexibleInstances for Generic Instance Derivation In Haskell, there isn't an extension that automatically derives the Bar IO instance without any extra code just because Foo IO exists, but you can get the behavior you want using the FlexibleInstances extension. Here's how to do it:
Step 1: Enable the FlexibleInstances Extension
Add this line at the very top of your Haskell file:
{-# LANGUAGE FlexibleInstances #-}
Step 2: Add a Generic Bar Instance
Since all methods of Bar have default implementations that rely on its superclass Foo, you can write a generic instance that applies to any type m which already has a Foo instance:
instance Foo m => Bar m where -- No need to define `bar` here—the default implementation from the class definition will be used automatically
Updated Working Code
Putting it all together, your code will compile successfully without needing an explicit Bar IO instance:
{-# LANGUAGE FlexibleInstances #-} class Foo m where foo :: String -> m Int class (Foo m) => Bar m where bar :: String -> m Int bar id = foo id instance Foo IO where foo _ = return 0 -- Generic instance: any type with a Foo instance automatically gets a Bar instance instance Foo m => Bar m where quux :: IO Int quux = foo "" baz :: IO Int baz = bar ""
When you call bar "" in baz, GHC resolves the Bar IO instance via the generic Foo m => Bar m declaration, since IO already has a valid Foo instance.
Handling Overlapping Instances (Optional)
If you later want to define a custom Bar instance for a specific type that overrides the generic one, enable the OverlappingInstances extension. For example:
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-} -- Generic fallback instance instance Foo m => Bar m where -- Custom Bar instance for IO that overrides the generic one instance Bar IO where bar _ = return 42
Just be careful with OverlappingInstances—it can introduce ambiguity if not used intentionally, so only enable it when you explicitly need this behavior.
Key Note vs. Scala Implicits
Unlike Scala's implicits, which can implicitly derive instances from superclasses, Haskell's type class system relies on explicit instance declarations. The generic instance approach using FlexibleInstances mimics the Scala behavior by explicitly stating that any Foo instance should also be a Bar instance using the default method implementations.
内容的提问来源于stack exchange,提问作者Piotr Jander

