Could not match type MyMaybe with type Maybe

Hi, I’m fairly new to PureScript and I’m trying to create a project for practicing purposes with examples and unit tests to get a more thorough understanding of the language. I’ve created my own versions of the data types Maybe and Either. I want to build a parser that disects multiple characters in a string. Here’s the code:

import Prelude (class Eq, class Ord, class Show, ($), (<), (>), (<>), (<<<), otherwise)

import Control.Applicative (class Applicative, pure)
import Control.Apply (class Apply, (<*>))
import Data.Bifunctor (class Bifunctor)
import Data.Functor (class Functor, map, (<$>))
import Data.Generic.Rep (class Generic)
import Data.Newtype (class Newtype)
import Data.Semigroup (class Semigroup)
import Data.Show.Generic (genericShow)
import Data.String.CodeUnits (uncons, fromCharArray)
import Data.Tuple (Tuple(..))

data MyMaybe a = Nothing | Just a

derive instance eqMyMaybe :: Eq a => Eq (MyMaybe a)
derive instance genericMyMaybe :: Generic (MyMaybe a) _

instance showMyMaybe :: Show a => Show (MyMaybe a) where
  show = genericShow

instance functorMyMaybe :: Functor MyMaybe where
  map f (Just x) = Just $ f x
  map _ Nothing  = Nothing

instance applyMyMaybe :: Apply MyMaybe where
  apply (Just f) x = f <$> x
  apply Nothing _  = Nothing

instance applicativeMyMaybe :: Applicative MyMaybe where
  pure = Just

data Either a b = Left a | Right b

derive instance eqEither :: (Eq a, Eq b) => Eq (Either a b)
derive instance ordEither :: (Ord a, Ord b) => Ord (Either a b)
derive instance functorEither :: Functor (Either a)
derive instance genericEither :: Generic (Either a b) _

instance showEither :: (Show a, Show b) => Show (Either a b) where
  show = genericShow

instance bifunctorEither :: Bifunctor Either where
  bimap f _ (Left x)  = Left $ f x
  bimap _ g (Right y) = Right $ g y

instance applyEither :: Apply (Either a) where
  apply (Right f) x = f <$> x
  apply (Left y) _  = Left y

instance applicativeEither :: Applicative (Either a) where
  pure = Right
  
type ParserState a = Tuple String a

class ParserError (e :: Type) where
  eof :: e

data PError = EOF

derive instance genericPError :: Generic PError _ 

instance showPError :: Show PError where 
  show = genericShow

instance parserErrorPError :: ParserError PError where
  eof = EOF

type ParseFunction e a = ParserError e => String -> Either e (ParserState a)

newtype Parser e a = Parser (ParseFunction e a)

instance functorParser :: Functor (Parser e) where
  map f p = Parser \s -> map f <$> parse p s

instance applyParser :: Apply (Parser e) where
  apply p1 p2 = Parser \s -> case parse p1 s of 
    Left err           -> Left err
    Right (Tuple s1 h) -> case parse p2 s1 of 
      Left err           -> Left err
      Right (Tuple s2 x) -> Right (Tuple s2 (h x))

instance applicativeParser :: Applicative (Parser e) where
  pure x = Parser \s -> pure (Tuple s x)

parse :: ∀ e a. Parser e a -> ParseFunction e a
parse (Parser f) = f

parse' :: ∀ a. Parser PError a -> ParseFunction PError a
parse' = parse

char :: ∀ e. Parser e Char
char = Parser \s -> case uncons s of
  Nothing             -> Left eof
  Just { head, tail } -> Right (Tuple tail head)

As soon as I try to compile this, I get the following error message:

[1/1 TypesDoNotUnify] src\Ch17.purs:160:3

  160    Nothing             -> Left eof
         ^^^^^^^

  Could not match type
    MyMaybe
  with type
    Maybe
  while trying to match type MyMaybe t2
    with type Maybe
                { head :: Char
                , tail :: String
                }
  while checking that expression case (uncons s) of
                                   Nothing -> Left eof
                                   (Just { head: head, tail: tail }) -> (apply Right) ((...) head)
    has type Either t0 (Tuple String t1)
  in value declaration char
  where t0 is an unknown type
        t1 is an unknown type
        t2 is an unknown type

Can anyone tell me how to solve this?

Hallo and welcome,

do you by chance import the usual Nothing value too? Can you show us your import-section of your code?

Hint: Name it MyMaybe or Option instead :wink:

Hi Carsten, thanks for the tip! In the above code I added all my imports and I changed the name Maybe to MyMaybe

I see now that the function uncons inside my char function uses the original Maybe from the Data.Maybe library instead of MyMaybe. But those 2 types should be Isomorphic, is there a way to use MyMaybe instead of Maybe?

Sadly no - it’s not structural typed for data and newtype - the name (including namespace) is the first thing that is matched when unifying two types.

But you could qualify the import: Don’t import the constructors instead do something like this:

import Data.Maybe as M

...
case (uncons s) of
    M.Nothing -> ...

Thanks a lot! Not what I was hoping for, but it’s a great solution! I was already trying to create my own version of uncons which only gave me more complexity and compile errors :sweat_smile:

Yeah … it’s probably not the best experience. Sure you can learn a lot but Maybe is among the core types that get used all over the place - so you pretty much would have to reimplement a lot of stuff.