0

I'm making a parser function for small strings that contain currency information.

I'm getting an error message about the regex syntax, =~, that is unclear to me.

Here is my code:

{-# LANGUAGE DeriveGeneric,  OverloadedStrings, FlexibleContexts, RankNTypes, KindSignatures, DataKinds #-}
import Data.Time
import Data.Text as T
import Text.Regex.PCRE

data Currency = USD | EUR | JPN deriving (Show, Generic)

-- -- Currency part
cparse :: Text -> Currency
cparse raw
    | (raw =~ "^\\$" :: Bool) = USD
    | (raw =~ "^¥" :: Bool)   = JPN
    | (raw =~ "^€" :: Bool)   = EUR
    | (raw =~ "USD$" :: Bool) = USD
    | (raw =~ "JPN$" :: Bool) = JPN
    | (raw =~ "EUR$" :: Bool) = EUR
    | otherwise               = USD

My tests for these conditions work as expected:

Prelude Text.Regex.PCRE> ("$12" =~ "^\\$" :: Bool)
True
Prelude Text.Regex.PCRE> ("¥12" =~ "^\\$" :: Bool)
False
Prelude Text.Regex.PCRE> ("¥12" =~ "^¥" :: Bool)
True
Prelude Text.Regex.PCRE> ("12USD" =~ "USD$" :: Bool)
True
Prelude Text.Regex.PCRE> ("12USF" =~ "USD$" :: Bool)
False

But when I try to define this function, here's my error:

<interactive>:14:8: error:
    • No instance for (RegexLike Regex Text) arising from a use of ‘=~’
    • In the expression: (raw =~ "^\\$" :: Bool)
      In a stmt of a pattern guard for
                     an equation for ‘cparse’:
        (raw =~ "^\\$" :: Bool)
      In an equation for ‘cparse’:
          cparse raw
            | (raw =~ "^\\$" :: Bool) = USD
            | (raw =~ "^¥" :: Bool) = JPN
            | (raw =~ "^€" :: Bool) = EUR
            | (raw =~ "USD$" :: Bool) = USD
            | (raw =~ "JPN$" :: Bool) = JPN
            | (raw =~ "EUR$" :: Bool) = EUR
            | otherwise = USD

Since the regex itself works, I don't think I'm using the regex library incorrectly, even though that is what the error strongly says.

My hunch is something is wrong in the way I wrote my guard, but I can't tell what. What am I getting wrong?

Mittenchops
  • 18,633
  • 33
  • 128
  • 246
  • 1
    In your manual tests you use `String`, not `Text`. – melpomene Apr 16 '19 at 20:27
  • Hmm, I don't understand. I have set overloadedstrings in my ghci session. So I should be using a text, right? – Mittenchops Apr 16 '19 at 20:28
  • 1
    Why would it use `Text`? – melpomene Apr 16 '19 at 20:29
  • Have you tried using [`Text.Regex.PCRE.Text`](https://hackage.haskell.org/package/regex-pcre-text)? – melpomene Apr 16 '19 at 20:31
  • 1
    In the Haddock, I don't see `Text` anywhere in the derives for `RegexLike`, just `String` and `ByteString`. – DarthFennec Apr 16 '19 at 20:43
  • 4
    `OverloadedStrings` means that a string literal can be used to create values of multiple different types, not just `Text`. In your tests, you don't specify a type for the string literals, so they default to `String`. In `cparse`, the declared type for `raw` forces the use to `Text`; `OverloadedStrings` just means that `'^\\$"` will have type `Text`, not that `=~` will work with `Text`. – chepner Apr 16 '19 at 21:02

0 Answers0