fcracker79
fcracker79

Reputation: 1218

Import monadic stuff from another module

I have the following module structure:

Module A:

module ModuleA where

newtype Parser p = P (String -> Maybe (p, String))

parse :: Parser p -> String -> Maybe (p, String)
parse (P p) = p

item :: Parser Char
item = P (\inp -> case inp of
                 [] -> Nothing
                 (x: xs) -> Just (x, xs))

Module B:

module ModuleB where

...

instance Alternative Parser where
    empty = P (\inp -> Nothing)
    (P a) <|> (P b) = P (\inp -> case a inp of
                                 Nothing -> b inp
                                 Just (x, v) -> Just (x, v)
                        )

Module C:


module ModuleC where

import ModuleA
import ModuleB
import Data.Char


conditionalParser :: (Char -> Bool) -> Parser Char
conditionalParser f = do
                                x <- item
                                if f x then return x else empty

The code does not compile, with error Variable not in scope: empty :: Parser Char. If I move the Alternative instance into the ModuleC module, it compiles.

How can I import the Alternative instance definition, so that it can be safely used? I have also tried using a qualified reference for empty, with no success.

Upvotes: 1

Views: 53

Answers (1)

Fyodor Soikin
Fyodor Soikin

Reputation: 80754

You are importing the instance definition from ModuleB just fine. It's the class definition that you're not importing, and it's in the class, not the instance, that the empty method is declared.

Add this at the top of ModuleC:

import Control.Applicative

That should do it.

Or, alternatively, you can re-export the Applicative class from ModuleB.


Note also that it's generally considered unsound to define instances in a module separate from both the type and the class. This may lead to subtle unexpected results with choosing the right instance down the line. This is called "orphan instance" and there is even a compiler warming against it.

Upvotes: 2

Related Questions