0

I have this core Haskell file : Relation.hs
It defines some data types

{-# LANGUAGE GADTs,MultiParamTypeClasses,ScopedTypeVariables,TypeSynonymInstances,FlexibleInstances #-}

module Relation where

data SchemaField schemaField where
  SchemaField :: (Eq fieldType) => {
    name :: String,
    fieldType :: fieldType,
    nullable :: Bool
  } -> SchemaField (String,fieldType,Bool)

data ValueField valueField where
  ValueField :: (Eq valueField,Ord valueField) => valueField -> ValueField valueField

type Schema schemaField = [SchemaField schemaField]

type MaybeValueField valueField = Maybe (ValueField valueField)
type Row valueField = [MaybeValueField valueField]
type Rows valueField = [Row valueField]

data Relation schemaField valueField = Relation {
  schema :: Schema schemaField,
  rows :: Rows valueField
  }

Then, I have the test file : RelationTest.hs
It needs to use below Relation constructor :

{-# LANGUAGE MultiParamTypeClasses #-}

module RelationTest where

import Relation (FromValueToSchema,bindType,schema,rows,Relation)

data FieldType =
  StringType | IntType -- Char | Bool | Integer | Float | Double
  deriving (Show,Eq)

consistentSchema = [SchemaField "name" StringType False,SchemaField "ID" IntType True]
createdRelation = Relation {schema = consistentSchema, rows = []}

But when I compile RelationTest.hs, I have this error I do not understand : Not in scope: data constructor ‘Relation’
From understanding, Relation constructor is well defined in Relation.hs.
I can remove the details in "import Relation ..." in RelationTest.hs and it works fine.
But I would like to keep detailed import.
When this import is removed, in GHCi interpreter, I can see Relation constructor type :

*Main> import Relation
*Main Relation> :t Relation
Relation
  :: Schema schemaField
     -> Rows valueField -> Relation schemaField valueField

So, what did I miss in my detailed import ?

I check those 2 StackOverflow threads, but I did not find any solution :

ymir
  • 93
  • 1
  • 9
  • 2
    you are only importing the type constructor of `Relation`. Change the import line to `import Relation (FromValueToSchema,bindType,schema,rows,Relation(..))` and it would resolve. – user1984 Nov 04 '21 at 18:37
  • Thank you user1984, I tried something like this but I did not work. Here are my tries : * import Relation (...,Relation(schemaField valueField)) * import Relation (...,Relation(schema rows)) * import Relation (...,Relation(Schema Rows)) * import Relation (...,Relation((Schema schemaField) (Rows valueField))) – ymir Nov 04 '21 at 18:52
  • 1
    please change the import to the exact import line I posted above and let me know if anything changes (like do you get a new error? if so, what is it, etc.). I'm asking this because, as far as I can tell, what you have tried is different than what I'm proposing – user1984 Nov 04 '21 at 18:55
  • it works fine now, thanks to user1984. But I do not understand the (..) synthax. Do you have any links or keyword so I can learn about this ? – ymir Nov 04 '21 at 19:08
  • Let me make this an answer. – user1984 Nov 04 '21 at 19:18
  • in short, `import MyType` just imports the type but none of its constructors. You can do `import MyType(Constructor)` or `MyType(Constructor1, Constructor2)` etc to explicitly import one or more of the constructors. But `import MyType(..)` imports *all* constructors of the type. – Robin Zigmond Nov 04 '21 at 19:34
  • Good use case for `-ddump-minimal-imports` – David Fox Nov 04 '21 at 20:03
  • @ymir The correct syntax for completely explicit import is `import Relation(Relation(Relation))`... yikes! The first one is module name, the next is data type name, and the last is data constructor name. If there were more constructors, they would be separated by commas, as in `import Relation(Relation(RelationA, RelationB))`. – Daniel Wagner Nov 05 '21 at 16:56

1 Answers1

2

In RelationTest.hs file, you are importing specific type constructors from the Relation module using the following:

import Relation (FromValueToSchema,bindType,schema,rows,Relation)

When it comes to data types, this only imports the type constructor. The data constructor(s), possible methods and field names are not imported. Adding a (..) to the end of a type constructor or class will import all of their possible members. Like follows:

import Relation (FromValueToSchema,bindType,schema,rows,Relation(..))

Section 5.3.1 of the Haskell Report states:

Exactly which entities are to be imported can be specified in one of the following three ways:

  1. The imported entities can be specified explicitly by listing them in parentheses. Items in the list have the same form as those in export lists, except qualifiers are not permitted and the `module modid' entity is not permitted. When the (..) form of import is used for a type or class, the (..) refers to all of the constructors, methods, or field names exported from the module.
user1984
  • 5,990
  • 2
  • 13
  • 32