Search code examples
haskellmoduleexportinstancetypeclass

How to import just specific instances in haskell


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 Doubles and not for Ints. But in my example, both instances get exported implicitly. Is there a way around it?


Solution

  • 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