0

I am trying to pattern-match Text to aeson Value using the String constructor, and am running into compile errors. The following example program illustrates the issue I've been running into.

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.Text
import qualified Data.Aeson

main = print $
  case ("here" :: Data.Text.Text) of
  (Data.Aeson.String x) -> "match"
  _                     -> "no match"

As shown I am trying to get the Text "here" to pattern-match into Aeson's 'String' Value constructor. I think that this program should pattern match the Text to Aeson String and print "match". But the program does not compile. Instead I get the following error:

$ ghc scratch.hs 
[1 of 1] Compiling Main             ( scratch.hs, scratch.o )

scratch.hs:9:4: error:
    • Couldn't match expected type ‘Data.Text.Text’
                  with actual type ‘Data.Aeson.Value’
    • In the pattern: Data.Aeson.String x
      In a case alternative: (Data.Aeson.String x) -> "match"
      In the second argument of ‘($)’, namely
        ‘case ("here" :: Data.Text.Text) of {
           (Data.Aeson.String x) -> "match"
           _ -> "no match" }’

It says the pattern expected Text whereas the actual type was aeson Value. But it is clearly Text as marked by the type annotation ("here" :: Data.Text.Text). I don't understand why I am getting this error. Pattern-matching Text to aeson Value via the String constructor appears to be done in this aeson tutorial, and I don't see why it does not also work in my example here.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
mherzl
  • 5,624
  • 6
  • 34
  • 75

1 Answers1

1

It says the pattern expected Text whereas the actual type was aeson Value. But it is clearly Text as marked by the type annotation

The value being matched is indeed of type Text. But the pattern you are matching against is not a pattern for the type Text; instead, it is a pattern for the type Value. You cannot match a value of one type against a pattern of another type, for obvious reasons.

There are many possible fixes, but it's difficult to choose one to suggest, because you have said little about what you are trying to do. Possibly you were intending to parse the Text into a Value and check which kind of value it was:

case decode (fromStrict (encodeUtf8 "\"match\"")) of
    Just (String x) -> "match"
    Just _ -> "no match"
    Nothing -> "invalid JSON"

However, I suspect that you are actually just misunderstanding how to use aeson, and should be writing a FromJSON instance (or using an existing one) rather than trying to muck about with Text values directly. For example, to parse a JSON value as Text, you might reuse the existing FromJSON instance for Text to write:

case decode "\"match\"" of
    Just v -> Data.Text.putStrLn v
    Nothing -> putStrLn "invalid JSON"

Again, both of these suggestions are pure speculation due to how light the question is on bigger-picture goals.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380