2

I am new to Haskell. I am trying to create a simple JSON API client, and have found one implemented for Twitter in Haskell. My current goal is outlined in this question, but the same thing is demonstrated below.

In that Twitter/Haskell API code, there is this snippet:

https://github.com/himura/twitter-types/blob/master/Web/Twitter/Types.hs#L577-L587

type EntityIndices = [Int]

data Entity a = Entity {
  entityBody :: a,                -- ^ The detail information of the specific entity types (HashTag, URL, User)
  entityIndices :: EntityIndices, -- ^ The character positions the Entity was extracted from
} deriving (Show, Eq)

instance FromJSON a => FromJSON (Entity a) where
  parseJSON v@(Object o) = Entity <$> parseJSON v
                                  <*> o .: "indices"
  parseJSON _ = mzero

What is happening here?

First, from my understanding, That data block is a Generalized Algebraic Data Type, because you are passing a parameter into the type data Entity a, and that a is being used in entityBody :: a.

Second, how do you instantiate that Entity generalized algebraic data type?

Finally, what is happening here?

instance FromJSON a => FromJSON (Entity a) where

What does that => mean?

I can break this into multiple questions if that helps, but it all seems sorta interconnected.

Community
  • 1
  • 1
Lance
  • 75,200
  • 93
  • 289
  • 503
  • This isn't an answer, but note that the ` ` syntax doesn't work in titles - it's taken and appears as a literal. – furkle Nov 02 '14 at 05:10
  • 3
    FYI, that’s an algebraic data type, but it isn’t a *generalized* algebraic data type. – icktoofay Nov 02 '14 at 05:39
  • `=>` reads like implication. `instance FromJSON a => FromJSON (Entity a) where` means, "given an instance FromJSON a, we can constructor an instance FromJSON (Entity a)", or "the existence of FromJSON a implies the existence of FromJSON (Entity a)". – user2407038 Nov 02 '14 at 15:44

1 Answers1

3

The definition for Entity

data Entity a = Entity {
  entityBody :: a,                -- ^ The detail information of the specific entity types (HashTag, URL, User)
  entityIndices :: EntityIndices, -- ^ The character positions the Entity was extracted from
} deriving (Show, Eq)

a can be of any type. There are no restrictions. The instance for FromJSON for Entity puts a restraint on the type of a. It is saying this instance of FromJSON for Entity the a type must also have an instance of FromJSON defined.

For example the show typeclass.

show :: Show a => a -> String

In order to call the show function the argument passed in a must have an instance of Show. The => just separates the typeclass constraints for the type definition.

So back to the FromJSON. If you define your own data type.

data Person = Person { name :: String } 

And write the code

let e = eitherDecode data :: Either String (Entity Person)

It won't compile because you haven't defined an instance of FromJSON for Person. If you create the instance then it will work.

instance FromJSON Person where
    parseJSON (Object o) = Person <$> o .: "name"
    parseJSON _ = mzero 
DiegoNolan
  • 3,766
  • 1
  • 22
  • 26