Reputation: 31
I think I'm going about this problem in a fundamentally incorrect way, but I'm not sure how to make an elegant solution in Haskell.
I would like to write a function which parses a string of JSON into some Haskell type. However, I don't know how to pass the type into my function (which I don't think I can do).
For example, I would like to do something like this:
data Foo = Foo { _a :: String } deriving (Generic, ToJSON, FromJSON)
data Bar = Bar { _b :: String } deriving (Generic, ToJSON, FromJSON)
parseSomething :: (FromJSON a) => a -> Maybe a
parseSomething a = (decode "..some json string...") :: Maybe a
Is this possible, or am I thinking about the problem incorrectly?
At the moment, I receive a type deduction error:
• Could not deduce (FromJSON a1) arising from a use of ‘decode’
from the context: FromJSON a
bound by the type signature for:
foo :: forall a. FromJSON a => a -> Maybe a
at src/Plumbing/Types.hs:60:1-35
Possible fix:
add (FromJSON a1) to the context of
an expression type signature:
forall a1. Maybe a1
• In the expression: decode "{\"_a\":\"foo\"}" :: (Maybe a)
In an equation for ‘foo’:
foo a = decode "{\"_a\":\"foo\"}" :: (Maybe a)
|
61 | foo a = decode "{\"_a\":\"foo\"}" :: (Maybe a)
Upvotes: 3
Views: 168
Reputation: 10939
You can use the type applications extension for this:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
import Data.Aeson
import GHC.Generics
data Foo = Foo { _a :: String } deriving (Show, Generic, ToJSON, FromJSON)
data Bar = Bar { _b :: String } deriving (Show, Generic, ToJSON, FromJSON)
parseSomething :: (FromJSON a) => Maybe a
parseSomething = decode "{ \"_a\": \"Hello\" }"
main :: IO ()
main = putStrLn $ show (foo, bar)
where
foo = parseSomething @Foo
bar = parseSomething @Bar
but honestly I see zero benefit of being able to write
foo = parseSomething @Foo
bar = parseSomething @Bar
over
foo = parseSomething :: Maybe Foo
bar = parseSomething :: Maybe Bar
Upvotes: 4