subprimeloads
subprimeloads

Reputation: 392

Trouble using a data constructor defined in an imported file

Say I have a queue implementation in a file and wanted to import it to work in a main file. I'm having trouble figuring out how to properly do so without getting a constructor error.

Say I have this in one file Queue1.hs

module Queue1 (Queue, mtq, ismt, addq, remq) where
data Queue a = Queue1 [a] deriving (Show)
-- multiple methods defined . . .

Then in my main file say I have:

import Queue1

And wanted to do this, which adds a list to the beginning of the Queue:

addq :: [a] -> Queue a -> Queue a
addq xs q = undefined

How exactly would I create the function so that I can use the Queue methods defined in another file?

I have created the following variations with no success:

adds xs (Queue q) = (xs:q)
error: Not in scope: data constructor ‘Queue’
   |
13 | adds xs (Queue q) = (xs:q)

I also tried defining another Queue in the file which didn't work:

data Queue a = Queue3 [a] deriving Show 
adds :: [a] -> Queue a -> Queue as
adds xs (Queue3 q) = Queue3(xs:q)

error:
    Ambiguous occurrence ‘Queue’
    It could refer to
       either ‘Queue1.Queue’,
              imported from ‘Queue1’ at lab3.hs:4:1-13
              (and originally defined at Queue1.hs:17:1-41)
           or ‘Main.Queue’, defined at lab3.hs:9:1

Can anyone point to what I'm doing wrong?

Upvotes: 2

Views: 204

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70407

Data constructors are not exported for a type by default. This allows us to write abstract types which can only be manipulated via a well-defined interface. A well-known example of this is Data.Map, which is internally a funny tree-like structure with lots of internal invariants, but the constructor isn't exported because the devs don't want you poking around and making invalid maps.

However, in this case, you want to export Queue, both the type and the constructor, as it looks like you want users to be able to construct and pattern match against your type. The syntax to export a specific constructor is

module Queue1 (Queue(Queue1), mtq, ismt, addq, remq) where

If you want to export all of the constructors (and record fields, if there are any), then you can use the shortcut wildcard syntax

module Queue1 (Queue(..), mtq, ismt, addq, remq) where

In this case, that's equivalent to the first example, but if you had several constructors, then .. would export them all.

Upvotes: 4

Related Questions