Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to import things already defined in the Prelude in Haskell

I'm trying to define a Foldable instance in Haskell and I have some problem with import.

So first try : module MyList where

import Data.Foldable

data MyList a = MyList [a]

instance Foldable (MyList) where
  foldr f b (MyList as) = foldr f b as

Result (normal but annoying)

Ambiguous occurrence `foldr'

So, I guess I have to hide it from the Prelude : module MyList where

import Prelude hiding (foldr)
import Data.Foldable

data MyList a = MyList [a]

instance Foldable (MyList) where
  foldr f b (MyList as) = foldr f b as

This compile, I load into ghci and try some basic stuff :

*MyList> foldr (:) "" (MyList "hello")
"hello"
*MyList> foldl (flip (:)) "" (MyList "hello")

<interactive>:1:0:
    Ambiguous occurrence `foldl'
    It could refer to either `Prelude.foldl', imported from Prelude at MyList.hs:4:0-28
                          or `Data.Foldable.foldl', imported from Data.Foldable at MyList.hs:5:0-19
*MyList>

So foldr works, but foldl doesn't. My first question is

Do I have to hide manually every single method defined in Data.Foldable from the Prelude is their a nice way to do it ?

.

To avoid this problem , I tried to do an qualified import : module MyList where

import qualified  Data.Foldable as F

data MyList a = MyList [a]

instance F.Foldable (MyList) where
  foldr f b (MyList as) = foldr f b as

Seems to compile in ghc but

*MyList> foldr (:) "" (MyList "hello")

<interactive>:1:14:
    Couldn't match expected type `[Char]'
           against inferred type `MyList Char'
    In the third argument of `foldr', namely `(MyList "hello")'
    In the expression: foldr (:) "" (MyList "hello")
    In the definition of `it': it = foldr (:) "" (MyList "hello")

foldr is not found but suprisingly F.foldr works in ghci.

*MyList> F.foldr (:) "" (MyList "hello")
"hello"

But in ghci only, if I'm trying to import MyList in file, foldr, F.foldr, MyList.F.foldr and MyList.foldr doesn't work.

Why does it work in ghci but not in real ?

I guess I have to import Data.Foldable again (and again in every files using MyList)

Is there a better way to do it (like exporting Data.Foldable in MyList) ?

(I'm a newbie in Haskell and especially with modules)


After having a couple of responses, it seems there is no clean solution to this problem. However, I'm pretty sure I'm not the first doing that, so

What is the common practice to deal with that kind of problem?

Thanks for you help.

like image 639
mb14 Avatar asked Jul 04 '10 17:07

mb14


People also ask

How do I import something into Haskell?

The syntax for importing modules in a Haskell script is import <module name>. This must be done before defining any functions, so imports are usually done at the top of the file. One script can, of course, import several modules. Just put each import statement into a separate line.

What does prelude do in Haskell?

Prelude is a module that contains a small set of standard definitions and is included automatically into all Haskell modules.

What is a qualified import?

A qualified import allows using functions with the same name imported from several modules, e.g. map from the Prelude and map from Data.

How do you define a module in Haskell?

Haskell's module design is relatively conservative: the name-space of modules is completely flat, and modules are in no way "first-class." Module names are alphanumeric and must begin with an uppercase letter. There is no formal connection between a Haskell module and the file system that would (typically) support it.


1 Answers

Why does it work in ghci but not in real?

Because in your GHCi session you were typing expressions in the context of the MyList module, so F.foldr was in scope, but if you import MyList into another module then only the names exported by MyList, and the other modules you imported, are in scope.

Your guess is correct - in every module using Data.Foldable.foldr, you have to

import qualified Data.Foldable as F

The names exported by a module are unqualified; the qualification or not of those names is decided when the module is imported.

There have been proposals over the years to allow exporting qualified names, but to date nothing has been implemented.

like image 196
Simon Marlow Avatar answered Oct 02 '22 19:10

Simon Marlow