Skip to content

Deprecate .:? (getFieldOptional) and .!= (defaultField) #63

@thomashoneyman

Description

@thomashoneyman

After speaking with @davezuch I realized (at his prompting) that the functions and operators for .:? and .!= are unnecessary and can be replaced without losing any functionality in this library.

For example, given this type:

newtype User = User
  { name :: String 
  , age :: Maybe Int
  , team :: String
  }

derive instance newtypeUser :: Newtype User _
derive newtype instance showUser :: Show User 

these two instances are identical:

instance decodeJsonUser :: DecodeJson User where
  decodeJson json = do
    obj <- decodeJson json
    name <- obj .: "name"
    age <- obj .:? "age"
    team <- obj .:? "team" .!= "Red Team"
    pure $ User { name, age, team }
    
instance decodeJsonUser :: DecodeJson User where
  decodeJson json = do
    obj <- decodeJson json
    name <- obj .: "name"
    age <- obj .: "age"
    team <- obj .: "team" <|> pure "Red Team"
    pure $ User { name, age, team }

Because the Maybe instance for .: already covers the case covered by .:?, and the functionality of .!= (providing a default value for a type which may not exist in the Json, but must exist in the decoded type) is covered by the use of Alternative: <|> pure default. In fact, this is even better, because it introduces to folks the ability to have fallbacks via Alternative rather than lead them to use an overly-specific operator.

> decodeJson =<< jsonParser """{ "name": "Tom", "age": 55, "team": "Blue Team" }""" :: Either String User
(Right { age: (Just 55), name: "Tom", team: "Blue Team" })

> decodeJson =<< jsonParser """{ "name": "Tom", "age": 55 }""" :: Either String User
(Right { age: (Just 55), name: "Tom", team: "Red Team" })

> decodeJson =<< jsonParser """{ "name": "Tom", "age": null }""" :: Either String User
(Right { age: Nothing, name: "Tom", team: "Red Team" })

Side note: I'm not sure that .:! needs to exist either. Its sole difference from .: applied to Maybe is that it will error on a key present with a null value instead of decoding to Nothing. I'm not sure when that would ever be the desired behavior. But that's a question for another day.

I'd like to open a PR which deprecates .:? and .!= and standardizes on just .: and <|> pure default.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions