Proxies, type level symbols, and JSON - haskell

I'm trying to add automagical json parsing to Data.Vinyl
Here is an instance for FromJSON for records with exactly one element.
It almost works, but I can't satisfy the KnownSymbol constraint, it seems to auto generate a new type variable on me.
instance (KnownSymbol sym, FromJSON a) => FromJSON (PlainRec '[ sym ::: a ]) where
parseJSON (Object v) = (field =:) <$> (v .: json_name)
where field = Field :: (sym ::: a)
json_name = T.pack $ show field
The error is
Could not deduce (KnownSymbol sym0) arising from a use of ‛show’
from the context (KnownSymbol sym, FromJSON a)
More context http://lpaste.net/101005
If I replace all instances of sym with "name", it works, and runs and it is wonderful. Now, I could use template Haskell to generate all the instances ahead of time, since I have a closed list of field names that I'll actually use, but that seems like such a shame. I know next to nothing about Data.Proxy, having just seen in used to define the show instance for the records of Data.Proxy.

You just have to enable ScopedTypeVariables.

Related

How to create an instance of Arbitrary for parametric types in Haskell

I'm following haskellbook.com and there is an exercise for QuickCheck, long history short I can't figure out how to implement a instance for arbitrary for my type because it has a parametric type
Here is the code
module First where
import Test.QuickCheck
-- I have this type that has a type parameter, it's a Maybe like
data Optional a = Some a | None deriving (Show, Eq)
-- I want to check that this is monoidal, but that is not the problem yet
newtype First' a =
First' { getFirst' :: Optional a }
deriving (Eq, Show)
-- Here I have an undefined. I simply cant do `instance Arbitrary (First String)`
-- And I cant place a concrete type on the undefined place. How can I implement
-- this type class for First' a?
instance (Arbitrary a) => Arbitrary (First' a) where
arbitrary = frequency [ (1, return (First' (Some undefined))) --- how I get rid of this undefined ?????
, (1, return (First' None))
]
I would like to have something like Some "foo" in place of Some undefined, but I cant
make a a concrete type, I'm struggling with this for some hours and just cant
come up with a solution.
What you want to do is use the Arbitrary instance for a. I can tell you know you need to do this because you already added Arbitrary a as a constraint to the instance, but you need to actually use it. For instance:
instance Arbitrary a => Arbitrary (First' a) where
arbitrary = frequency [ (1, First' . Some <$> arbitrary) -- here we have `arbitrary :: Gen a`
, (1, return (First' None))
]
But really, you should go one step further. Rather than just making an instance for First' a, you can first make an instance for Optional a that will make your First' instance even easier. Consider:
instance Arbitrary a => Arbitrary (Optional a) where
arbitrary = oneof [ Some <$> arbitrary -- here we have `arbitrary :: Gen a`
, return None
]
instance Arbitrary a => Arbitrary (First' a) where
arbitrary = First' <$> arbitrary -- this one is `arbitrary :: Gen (Optional a)`
(Note that oneof is like frequency where all the frequency numbers are the same.)

Default to a typeclass when a data type does not instantiate it [duplicate]

What I'd like to achieve is that any instance of the following class (SampleSpace) should automatically be an instance of Show, because SampleSpace contains the whole interface necessary to create a String representation and hence all possible instances of the class would be virtually identical.
{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio (Rational)
class SampleSpace space where
events :: Ord a => space a -> [a]
member :: Ord a => a -> space a -> Bool
probability :: Ord a => a -> space a -> Rational
instance (Ord a, Show a, SampleSpace s) => Show (s a) where
show s = showLines $ events s
where
showLines [] = ""
showLines (e:es) = show e ++ ": " ++ (show $ probability e s)
++ "\n" ++ showLines es
Since, as I found out already, while matching instance declarations GHC only looks at the head, and not at contraints, and so it believes Show (s a) is about Rational as well:
[1 of 1] Compiling Helpers.Probability ( Helpers/Probability.hs, interpreted )
Helpers/Probability.hs:21:49:
Overlapping instances for Show Rational
arising from a use of ‘show’
Matching instances:
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance (Ord a, Show a, SampleSpace s) => Show (s a)
-- Defined at Helpers/Probability.hs:17:10
In the expression: show
In the first argument of ‘(++)’, namely ‘(show $ probability e s)’
In the second argument of ‘(++)’, namely
‘(show $ probability e s) ++ "" ++ showLines es
Question: is it possible (otherwise than by enabling overlapping instances) to make any instance of a typeclass automatically an instance of another too?
tl;dr: don't do that, or, if you insist, use -XOverlappingInstances.
This is not what the Show class is there for. Show is for simply showing plain data, in a way that is actually Haskell code and can be used as such again, yielding the original value.
SampleSpace should perhaps not be a class in the first place. It seems to be basically the class of types that have something like Map a Rational associated with them. Why not just use that as a field in a plain data type?
Even if we accept the design... such a generic Show instance (or, indeed, generic instance for any single-parameter class) runs into problems when someone makes another instance for a concrete type – in the case of Show, there are of course already plenty of instances around. Then how should the compiler decide which of the two instances to use? GHC can do it, in fact: if you turn on the -XOverlappingInstances extension, it will select the more specific one (i.e. instance SampleSpace s => Show (s a) is “overridden” by any more specific instance), but really this isn't as trivial as may seem – what if somebody defined another such generic instance? Crucial to recall: Haskell type classes are always open, i.e. basically the compiler has to assume that all types could possibly in any class. Only when a specific instance is invoke will it actually need the proof for that, but it can never proove that a type isn't in some class.
What I'd recommend instead – since that Show instance doesn't merely show data, it should be made a different function. Either
showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String
or indeed
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
where SampleSpace is a single concrete type, instead of a class.

Make a typeclass instance automatically an instance of another

What I'd like to achieve is that any instance of the following class (SampleSpace) should automatically be an instance of Show, because SampleSpace contains the whole interface necessary to create a String representation and hence all possible instances of the class would be virtually identical.
{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio (Rational)
class SampleSpace space where
events :: Ord a => space a -> [a]
member :: Ord a => a -> space a -> Bool
probability :: Ord a => a -> space a -> Rational
instance (Ord a, Show a, SampleSpace s) => Show (s a) where
show s = showLines $ events s
where
showLines [] = ""
showLines (e:es) = show e ++ ": " ++ (show $ probability e s)
++ "\n" ++ showLines es
Since, as I found out already, while matching instance declarations GHC only looks at the head, and not at contraints, and so it believes Show (s a) is about Rational as well:
[1 of 1] Compiling Helpers.Probability ( Helpers/Probability.hs, interpreted )
Helpers/Probability.hs:21:49:
Overlapping instances for Show Rational
arising from a use of ‘show’
Matching instances:
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance (Ord a, Show a, SampleSpace s) => Show (s a)
-- Defined at Helpers/Probability.hs:17:10
In the expression: show
In the first argument of ‘(++)’, namely ‘(show $ probability e s)’
In the second argument of ‘(++)’, namely
‘(show $ probability e s) ++ "" ++ showLines es
Question: is it possible (otherwise than by enabling overlapping instances) to make any instance of a typeclass automatically an instance of another too?
tl;dr: don't do that, or, if you insist, use -XOverlappingInstances.
This is not what the Show class is there for. Show is for simply showing plain data, in a way that is actually Haskell code and can be used as such again, yielding the original value.
SampleSpace should perhaps not be a class in the first place. It seems to be basically the class of types that have something like Map a Rational associated with them. Why not just use that as a field in a plain data type?
Even if we accept the design... such a generic Show instance (or, indeed, generic instance for any single-parameter class) runs into problems when someone makes another instance for a concrete type – in the case of Show, there are of course already plenty of instances around. Then how should the compiler decide which of the two instances to use? GHC can do it, in fact: if you turn on the -XOverlappingInstances extension, it will select the more specific one (i.e. instance SampleSpace s => Show (s a) is “overridden” by any more specific instance), but really this isn't as trivial as may seem – what if somebody defined another such generic instance? Crucial to recall: Haskell type classes are always open, i.e. basically the compiler has to assume that all types could possibly in any class. Only when a specific instance is invoke will it actually need the proof for that, but it can never proove that a type isn't in some class.
What I'd recommend instead – since that Show instance doesn't merely show data, it should be made a different function. Either
showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String
or indeed
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
where SampleSpace is a single concrete type, instead of a class.

How does `instance FromJSON a => FromJSON (Entity a)` work in Haskell?

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.
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

Ignoring/Overriding an Instance generated using TemplateHaskell

I'm using Aeson for some client-server stuff that I'm doing, encoding ADTs as Json. I'm using Data.Aeson.TH to generate the toJSON instances I need, but the instances generated for Map types are really ugly and awful to deal with.
I've defined my own, simpler encoding which just treats them as lists:
instance (ToJSON a, ToJSON b) => ToJSON (Map a b) where
toJSON m = toJSON $ toList m
Naturally, when I use this in my code, I get a Duplicate instance declarations error.
Is there a way to resolve this? I need to either tell Template Haskell NOT to generate the ToJson instance for Map, or I need to tell GHC to ignore that instance and use the one I supply. Can either of these be done?
Note that this isn't an "overlapping-instances" problem. I want to completely throw out the one instance, not mix it with the other one.
To tell GHC to ignore library-provided instance and use your own instead, you can wrap Map in a newtype:
newtype PrettyMap key val = PrettyMap (Map key val)
instance (ToJSON a, ToJSON b) => ToJSON (PrettyMap a b) where
toJSON (PrettyMap m) = toJSON $ toList m
Another solution is to really use OverlappingInstances:
data MyData = ...
$(deriveToJSON ... ''MyData)
instance ToJSON (Map Text MyData) where
toJSON = toJSON . toList

Resources