Reputation: 83
I'm facing the following problem: I have multiple instances of a type class defined in a module but don't want to export all of them. How can I do that?
module SomeModule
( calculate
)
where
class Something a where
calculate :: a -> Int
instance Something Double where
calculate x = calculate $ roundToInt x
instance Something Int where
calculate x = doSomething x
roundToInt :: Double -> Int
roundToInt = round
doSomething :: Int -> Int
doSomething _ = 42
In this (simplified) example I have two instances of the type class Something
which depend on each other, but I just would like to export the instance for Double
s and not for Int
s. But in my example, both instances get exported implicitly. Is there a way around it?
Upvotes: 3
Views: 333
Reputation: 152682
You can make the instances you want to hide be on a newtype
that isn't exported.
module SomeModule (calculate) where
newtype NotInt = NotInt Int
class Something a where calculate :: a -> Int
instance Something Double where calculate x = calculate (NotInt (round x))
instance Something NotInt where calculate _ = 42
If there are many instances you do not want to export, a parameterized newtype might be less boilerplate.
{-# LANGUAGE FlexibleInstances #-}
module SomeModule (calculate) where
newtype Hidden a = Hidden a
class Something a where calculate :: a -> Int
instance Something Double where calculate x = calculate (Hidden (round x :: Int))
instance Something (Hidden Int) where calculate _ = 42
Another option is not to define the instance in the first place, and simply use a different name than the class's method name for the implementation of the other method you care about.
module SomeModule (calculate) where
class Something a where calculate :: a -> Int
instance Something Double where calculate x = calculateInt (round x)
calculateInt :: Int -> Int
calculateInt _ = 42
Upvotes: 6