user2757025
user2757025

Reputation:

Alias a module defined in the same file in Haskell

I've got a module like that:

module Foo.Bar (
  Bar,
  not
) where
data Bar = Some Int | Other Int
not (Some x) = ...
not (Other x) = Foo.Bar.not $ Some x

As you see, I have to write Foo.Bar.not because not is defined in Prelude.

Is there a way to alias Foo.Bar to e.g. B so that I can write not (Other x) = B.not $ Some x in the very file where not is defined?

Upvotes: 2

Views: 218

Answers (5)

Zeta
Zeta

Reputation: 105885

Is there a way to alias Foo.Bar to e.g. B [...]?

While I'm not sure whether there is a way to alias a module in itself, you could easily alias not:

module Foo.Bar (
   Bar,
   Foo.Bar.not
 ) where

data Bar = Some Int | Other Int

notBar, not :: Bar -> Bool
notBar (Some  x) = ...
notBar (Other x) = notBar (Some x)

-- Use 'notBar' in this module, but export only 'not'.    
not = notBar

Given that notBar and B.not differ only a single character in length, I think this is more or less a valid solution. Furthermore, it doesn't depend on any compiler quirks.

Alternatively, hide the bindings that use the same name from Prelude:

module Foo.Bar (
   Bar,
   not
 ) where

import Prelude hiding (not)    

data Bar = Some Int | Other Int

not :: Bar -> Bool
not (Some  x) = ...
not (Other x) = notBar (Some x)

Upvotes: 1

user2757025
user2757025

Reputation:

It seems like this isn't possible using anything compliant with the Haskell specification and working in GHC.

Anyway, there are ways a similar result can be achieved:

  • As @leftaroundabout pointed out, import Prelude hiding (not) will help.
  • @PyRulez' answer suggests creating a module called B and exporting that module within Foo.Bar
  • @Zeta's answer suggests aliasing Foo.Bar.not to notBar

Upvotes: 0

Christopher King
Christopher King

Reputation: 10951

Here is a GHC compatible answer, although its a bit of a clutch:

-- B.hs
module B (
  Bar,
  B.not
) where
data Bar = Some Int | Other Int
not (Some x) = undefined
not (Other x) = B.not $ Some x
-- Foo.Bar.hs
module Foo.Bar (module Foo.Bar) where
import B as Foo.Bar

When Foo.Bar is imported, Bar, not, Foo.Bar.Bar and Foo.Bar.not are provided (the first two are suppresed if Foo.Bar is imported qualified.)

Upvotes: 0

Daniel Wagner
Daniel Wagner

Reputation: 152867

I think it should be technically possible, if a bit painful, in GHC. For example, I would expect things to work if you produced the following two files (following the documentation on mutual recursion):

-- Foo/Bar.hs-boot
module Foo.Bar where
import Prelude(Either)
not :: Either a a -> a

-- Foo/Bar.hs
module Foo.Bar where
import Prelude (Either(..))
import {-# SOURCE #-} Foo.Bar as B
not (Left x) = x
not (Right x) = B.not (Left x)

However, when I try this, I get a complaint that B.not is not in scope. I suspect this is a bug in GHC, and have filed a ticket here to see if the devs agree.

Upvotes: 2

Christopher King
Christopher King

Reputation: 10951

This should work

module Foo.Bar (
  Bar,
  B.not
) where

import qualified Foo.Bar as B (not)

data Bar = Some Int | Other Int
not (Some x) = undefined
not (Other x) = B.not $ Some x

be warned though, that if you are using GHC, you will probably need to do some extra work: https://wiki.haskell.org/Mutually_recursive_modules#GHC

Upvotes: 0

Related Questions