tags:

views:

201

answers:

1

I am learning Haskell. I am on the 8th chapter of this book. The main thing I've learned so far is that Haskell is very unfriendly to me and it bites my ass where possible. Moreover... Heck! Enough mourning, to business.

Here is the code:

module GlobRegex (
  globToRegex,
  matchesGlob
) where

import Text.Regex.Posix
import Text.Regex.Posix.String
import Text.Regex.Base.RegexLike

data CaseOpt = Case | NoCase
  deriving (Eq)

matchesGlob :: String -> String -> CaseOpt -> Bool
matchesGlob name pat caseopt = match regex name where
  regex = case caseopt of
               NoCase -> makeRegexOpts (defaultCompOpt + compIgnoreCase) defaultExecOpt (globToRegex pat)
               Case -> makeRegex (globToRegex pat)

globToRegex :: String -> String
...

And here is how it fails to compile:

Prelude Text.Regex.Posix Text.Regex.Base.RegexLike> :load globtoregex\GlobRegex.
hs
[1 of 1] Compiling GlobRegex        ( globtoregex\GlobRegex.hs, interpreted )

globtoregex\GlobRegex.hs:14:31:
    No instance for (RegexLike regex [Char])
      arising from a use of `match' at globtoregex\GlobRegex.hs:14:31-46
    Possible fix:
      add an instance declaration for (RegexLike regex [Char])
    In the expression: match regex name
    In the definition of `matchesGlob':
        matchesGlob name pat caseopt
                      = match regex name
                      where
                          regex = case caseopt of {
                                    NoCase
                                      -> makeRegexOpts
                                           (defaultCompOpt + compIgnoreCase)
                                           defaultExecOpt
                                           (globToRegex pat)
                                    Case -> makeRegex (globToRegex pat) }

globtoregex\GlobRegex.hs:17:23:
    No instance for (RegexMaker regex CompOption execOpt String)
      arising from a use of `makeRegex'
                   at globtoregex\GlobRegex.hs:17:23-49
    Possible fix:
      add an instance declaration for
      (RegexMaker regex CompOption execOpt String)
    In the expression: makeRegex (globToRegex pat)
    In a case alternative: Case -> makeRegex (globToRegex pat)
    In the expression:
        case caseopt of {
          NoCase
            -> makeRegexOpts
                 (defaultCompOpt + compIgnoreCase) defaultExecOpt (globToRegex p
at)
          Case -> makeRegex (globToRegex pat) }
Failed, modules loaded: none.

To my best understanding, Text.Regex.Posix.String provides instances for RegexLike Regex String and RegexMaker Regex CompOption ExecOption String, so it should work. On the other hand, I can see that regex in the error message is type variable, not a concrete type, so, perhaps not... Anyway, this is where I am stuck.

May be there is a common pattern for resolving no instance for type of problems? Or, in Haskell terms, instance of SmartGuess typeclass for no instance for?

+3  A: 

You're in a corner of the library that is pretty dark to my eyes. But I notice in your error message that the compiler says regex where you said Regex. Your code is too polymorphic, so almost certainly you have nontermination somewhere or you are passing the wrong arguments to something (and ignoring an argument that then becomes polymorphic).

Type-class hell is no fun, but I think you might get a more informative error message if you put a type signature for regex into the where clause. I can't make out what type it's supposed to be, but if you know, this may resolve the instance problem into a more tractable sort of type error.

I hate type-class hell.

Norman Ramsey
Another thing is that the `RegexOptions` class has a type parameter called "regex". It's not clear to me which `regex` the error message is referring to.
Michael Steele