Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I export typeclasses?

I am creating a file, Common.hs, which exports functions I commonly use. It also replaces some of Prelude's functions with versions I prefer:

-- Common.hs
module Common 
import qualified Prelude as Prelude
import qualified Data.Foldable as Foldable

sum      = Foldable.sum  -- I want to replace Prelude's sum
print    = Prelude.print -- I want to export Prelude's print
type Int = Prelude.Int   -- I want to export Prelude's Int
... etc (huge list) ...

This way, whenever I create a new Haskell file, I just have to import Common and compile it with -XNoImplicitPrelude:

-- Test.hs
import Common
main = print (sum [1,2,3]) -- will be the `sum` version I want

This approach seems to work, but I couldn't figure how to export typeclasses:

-- Test.hs
import Common
import Prelude (Show)

data Foo = Foo Int Int deriving Show

main = print (Foo 1 2)

Notice I had to manually import Prelude's Show. Is it possible to make Common.hs export it?

like image 729
MaiaVictor Avatar asked Aug 10 '15 20:08

MaiaVictor


1 Answers

You have to explicitly re-export type classes (meaning you'll also have to explicitly export everything else), i.e.

Your Prelude:

module CustomPrelude (
  sum,
  product,
  Prelude.IO,
  Prelude.String,
  Prelude.print,
  Prelude.Show,
  Prelude.show,
  (Prelude.$),
  Prelude.Int,
  (++)
  )
where

import qualified Prelude
import Data.Foldable
import Data.Monoid

(++) :: Monoid m => m -> m -> m
(++) = mappend

Usage:

{-# LANGUAGE NoImplicitPrelude #-}
module PreludeTest where

import CustomPrelude

data A x = A x x

instance Show x => Show (A x) where
    show (A x y) = "A " ++ show x ++ " " ++ show y

main :: IO ()
main = print $ A (1::Int) 2

To save yourself some typing (and to keep your sanity while editing), you'd probably want to do: A) Split your new prelude into several specialized files B) Do module exports so you don't have to explicitly repeat everything

E.g.:

module CustomPrelude.Classes (Show,show,Functor,fmap, Monoid,mempty,mappend, Monad,return,(>>=))
where

import Data.Monoid

module CustomPrelude.Functions (
  module ReExport,
  Prelude.print,
  Prelude.IO, -- ok these technically aren't functions, but I didn't want to make yet another module just for demonstration purposes
  Prelude.String,
  Prelude.Int,
  (Prelude.$),
  (++)
)
where

import qualified Prelude
import Data.Foldable as ReExport
import Data.Traversable as ReExport
import Data.Monoid as ReExport


(++) :: Monoid m => m -> m -> m
(++) = mappend

module CustomPrelude (
  module P
  )
where

import CustomPrelude.Classes as P
import CustomPrelude.Functions as P

Note that you can save yourself quite a bit of typing work by renaming your reexported modules all to the same name when importing them.

like image 120
Cubic Avatar answered Sep 23 '22 02:09

Cubic