
Sjoerd Visscher wrote:
In the case of Dual [1] `mappend` Dual [2] there's no need to do any unwrapping. There is if you say: l :: [Int] l = Dual [1] `mappend` Dual [2]
The way I think this could work is that when the type checker detects a type error, it will first try to resolve it by newtype unwrapping (or wrapping even).
So if I have: l :: Dual [Int] l = [1] `mappend` [2] It will wrap after the mappend, rather than before? But: l :: Dual [Int] l = Dual [1] `mappend` [2] Would wrap the RHS in Dual? Does this version unwrap the LHS: l :: [Int] l = Dual [1] `mappend` [2] And finally, what about: l :: [Int] l = Dual [1] `mappend` Endo [2] Automatic wrapping and unwrapping, like automatic coercions, look like an opportunity for surprising behaviour. OTOH, perhaps some sort of deriving mechanism would be good. To revisit someone's previous suggestion, perhaps you could allow functions in the deriving clause, so that if you have: f :: Foo -> Foo -> Foo newtype MyFoo = MyFoo {getFoo :: Foo} deriving (f as g) will generate: g :: MyFoo -> MyFoo -> MyFoo g x y = Foo (f (getFoo x) (getFoo y)) I think it's not something worth adding (too subtle), but I thought I'd throw it in as a possibility. Neil.