(Generically) Build Parsers from custom data types? - haskell

I'm working on a network streaming client that needs to talk to the server. The server encodes the responses in bytestrings, for example, "1\NULJohn\NULTeddy\NUL501\NUL", where '\NUL' is the separator. The above response translates to "This is a message of type 1(hard coded by the server), which tells the client what the ID of a user is(here, the user id of "John Teddy" is "501").
So naively I define a custom data type
data User
{ firstName :: String
, lastName :: String
, id :: Int
}
and a parser for this data type
parseID :: Parser User
parseID = ...
Then one just writes a handler to do some job(e.g., write to a database) after the parser succesfully mathes a response like this. This is very straightforward.
However, the server has almost 100 types of different responses like this that the client needs to parse. I suspect that there must be a much more elegant way to do the job rather than writing 100 almost identical parsers like this, because, after all, all haksell coders are lazy. I am a total newbie to generic programming so can some one tell me if there is a package that can do this job?

For these kinds of problems I turn to generics-sop instead of using generics directly. generics-sop is built on top of Generics and provides functions for manipulating all the fields in a record in a uniform way.
In this answer I use the ReadP parser which comes with base, but any other Applicative parser would do. Some preliminary imports:
{-# language DeriveGeneric #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language TypeFamilies #-}
{-# language DataKinds #-}
{-# language TypeApplications #-} -- for the Proxy
import Text.ParserCombinators.ReadP (ReadP,readP_to_S)
import Text.ParserCombinators.ReadPrec (readPrec_to_P)
import Text.Read (readPrec)
import Data.Proxy
import qualified GHC.Generics as GHC
import Generics.SOP
We define a typeclass that can produce an Applicative parser for each of its instances. Here we define only the instances for Int and Bool:
class HasSimpleParser c where
getSimpleParser :: ReadP c
instance HasSimpleParser Int where
getSimpleParser = readPrec_to_P readPrec 0
instance HasSimpleParser Bool where
getSimpleParser = readPrec_to_P readPrec 0
Now we define a generic parser for records in which every field has a HasSimpleParser instance:
recParser :: (Generic r, Code r ~ '[xs], All HasSimpleParser xs) => ReadP r
recParser = to . SOP . Z <$> hsequence (hcpure (Proxy #HasSimpleParser) getSimpleParser)
The Code r ~ '[xs], All HasSimpleParser xs constraint means "this type has only one constructor, the list of field types is xs, and all the field types have HasSimpleParser instances".
hcpure constructs an n-ary product (NP) where each component is a parser for the corresponding field of r. (NP products wrap each component in a type constructor, which in our case is the parser type ReadP).
Then we use hsequence to turn a n-ary product of parsers into the parser of an n-ary product.
Finally, we fmap into the resulting parser and turn the n-ary product back into the original r record using to. The Z and SOP constructors are required for turning the n-ary product into the sum-of-products the to function expects.
Ok, let's define an example record and make it an instance of Generics.SOP.Generic:
data Foo = Foo { x :: Int, y :: Bool } deriving (Show, GHC.Generic)
instance Generic Foo -- Generic from generics-sop
Let's check if we can parse Foo with recParser:
main :: IO ()
main = do
print $ readP_to_S (recParser #Foo) "55False"
The result is
[(Foo {x = 55, y = False},"")]

You can write your own parser - but there is already a package that can do the parsing for you: cassava and while SO is usually not a place to search for library recommendations, I want to include this answer for people looking for a solution, but not having the time to implement this themselves and looking for a solution that works out of the box.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
import Data.Csv
import Data.Vector
import Data.ByteString.Lazy as B
import GHC.Generics
data Person = P { personId :: Int
, firstName :: String
, lastName :: String
} deriving (Eq, Generic, Show)
-- the following are provided by friendly neighborhood Generic
instance FromRecord Person
instance ToRecord Person
main :: IO ()
main = do B.writeFile "test" "1\NULThomas\NULof Aquin"
Right thomas <- decodeWith (DecodeOptions 0) NoHeader <$>
B.readFile "test"
print (thomas :: Vector Person)
Basically cassava allows you to parse all X-separated structures into a Vector, provided you can write down a FromRecord instance (which needs a parseRecord :: Parser … function to work.
Side note on Generic until recently I thought - EVERYTHING - in haskell has a Generic instance, or can derive one. Well this is not the case I wanted to serialize some ThreadId to CSV/JSON and happened to find out unboxed types are not so easily "genericked"!
And before I forget it - when you speak of streaming and server and so on there is cassava-conduit that might be of help.

Related

List constructor names of a Haskell type?

conNameOf allows me to display the constructor name of a given piece of data, given that type is an instance of Generic.
What I'd like is something similar. For a given type, I want to get the full list of constructor names. For example:
data Nat = Z | S Nat
deriving (Generic)
-- constrNames (Proxy :: Proxy Nat) == ["Z", "S"]
Does something like constrNames exist? If not, how can I write it?
The function conNames from module Generics.Deriving.ConNames in package generic-deriving provides this functionality. It takes a term of the given type, though its value is not used, so you can use undefined:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Generics.Deriving.ConNames
import Data.Proxy
data Nat = Z | S Nat deriving (Generic)
main = print $ conNames (undefined :: Nat)
gives:
λ> main
["Z","S"]

Is there a canonical way of comparing/changing one/two records in haskell?

I want to compare two records in haskell, without defining each change in the datatype of the record with and each function of 2 datas for all of the elements of the record over and over.
I read about lens, but I could not find an example for that,
and do not know where begin to read in the documentation.
Example, not working:
data TheState = TheState { number :: Int,
truth :: Bool
}
initState = TheState 77 True
-- not working, example:
stateMaybe = fmap Just initState
-- result should be:
-- ANewStateType{ number = Just 77, truth = Just True}
The same way, I want to compare the 2 states:
state2 = TheState 78 True
-- not working, example
stateMaybe2 = someNewCompare initState state2
-- result should be:
-- ANewStateType{ number = Just 78, truth = Nothing}
As others have mentioned in comments, it's most likely easier to create a different record to hold the Maybe version of the fields and do the manual conversion. However there is a way to get the functor like mapping over your fields in a more automated way.
It's probably more involved than what you would want but it's possible to achieve using a pattern called Higher Kinded Data (HKD) and a library called barbies.
Here is a amazing blog post on the subject: https://chrispenner.ca/posts/hkd-options
And here is my attempt at using HKD on your specific example:
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
-- base
import Data.Functor.Identity
import GHC.Generics (Generic)
-- barbie
import Data.Barbie
type TheState = TheState_ Identity
data TheState_ f = TheState
{ number :: f Int
, truth :: f Bool
} deriving (Generic, FunctorB)
initState :: TheState
initState = TheState (pure 77) (pure True)
stateMaybe :: TheState_ Maybe
stateMaybe = bmap (Just . runIdentity) initState
What is happening here, is that we are wrapping every field of the record in a custom f. We now get to choose what to parameterise TheState with in order to wrap every field. A normal record now has all of its fields wrapped in Identity. But you can have other versions of the record easily available as well. The bmap function let's you map your transformation from one type of TheState_ to another.
Honestly, the blog post will do a much better job at explaining this than I would. I find the subject very interesting, but I am still very new to it myself.
Hope this helped! :-)
How to make a Functor out of a record. For that I have an answer: apply the function to > all of the items of the record.
I want to use the record as an heterogenous container / hashmap, where
the names determine the values-types
While there's no "easy", direct way of doing this, it can be accomplished with several existing libraries.
This answer uses red-black-record library, which is itself built over the anonymous products of sop-core. "sop-core" allows each field in a product to be wrapped in a functor like Maybe and provides functions to manipulate fields uniformly. "red-black-record" inherits this, adding named fields and conversions from normal records.
To make TheState compatible with "red-black-record", we need to do the following:
{-# LANGUAGE DataKinds, FlexibleContexts, ScopedTypeVariables,
DeriveGeneric, DeriveAnyClass,
TypeApplications #-}
import GHC.Generics
import Data.SOP
import Data.SOP.NP (NP,cliftA2_NP) -- anonymous n-ary products
import Data.RBR (Record, -- generalized record type with fields wrapped in functors
I(..), -- an identity functor for "simple" cases
Productlike, -- relates a map of types to its flattened list of types
ToRecord, toRecord, -- convert a normal record to its generalized form
RecordCode, -- returns the map of types correspoding to a normal record
toNP, fromNP, -- convert generalized record to and from n-ary product
getField) -- access field from generalized record using TypeApplication
data TheState = TheState { number :: Int,
truth :: Bool
} deriving (Generic,ToRecord)
We auto-derive the Generic instance that allows other code to introspect the structure of the datatype. This is needed by ToRecord, that allows conversion of normal records into their "generalized forms".
Now consider the following function:
compareRecords :: forall r flat. (ToRecord r,
Productlike '[] (RecordCode r) flat,
All Eq flat)
=> r
-> r
-> Record Maybe (RecordCode r)
compareRecords state1 state2 =
let mapIIM :: forall a. Eq a => I a -> I a -> Maybe a
mapIIM (I val1) (I val2) = if val1 /= val2 then Just val2
else Nothing
resultNP :: NP Maybe flat
resultNP = cliftA2_NP (Proxy #Eq)
mapIIM
(toNP (toRecord state1))
(toNP (toRecord state2))
in fromNP resultNP
It compares two records whatsoever that have ToRecord r instances, and also a corresponding flattened list of types that all have Eq instances (the Productlike '[] (RecordCode r) flat and All Eq flat constraints).
First it converts the initial record arguments to their generalized forms with toRecord. These generalized forms are parameterized with an identity functor I because they come from "pure" values and there aren't any effects are play, yet.
The generalized record forms are in turn converted to n-ary products with toNP.
Then we can use the cliftA2_NP function from "sop-core" to compare accross all fields using their respective Eq instances. The function requires specifying the Eq constraint using a Proxy.
The only thing left to do is reconstructing a generalized record (this one parameterized by Maybe) using fromNP.
An example of use:
main :: IO ()
main = do
let comparison = compareRecords (TheState 0 False) (TheState 0 True)
print (getField #"number" comparison)
print (getField #"truth" comparison)
getField is used to extract values from generalized records. The field name is given as a Symbol by way of -XTypeApplications.

Is there a way to shorten this deriving clause?

Is there a way to write the following:
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveAnyClass #-}
data X = A | B | C
deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SMTValue)
So that the deriving clause can be shortened somehow, to something like the following:
data X = A | B | C deriving MyOwnClass
I'd like to avoid TH if at all possible, and I'm happy to create a new class that has all those derived classes as its super-class as necessary (as in MyOwnClass above), but that doesn't really work with the deriving mechanism. With constraint kinds extension, I found that you can write this:
type MyOwnClass a = (Eq a, Ord a, Show a, Read a, Data a, SymWord a, HasKind a, SMTValue a)
Unfortunately, I cannot put that in the deriving clause. Is there some magic to make this happen?
EDIT From the comments, it appears TH might be the only viable choice here. (The CPP macro is really not OK!) If that's the case, the sketch of a TH solution will be nice to see.
There's bad and easy way to do it and good but hard way. As Silvio Mayolo said you can use TemplateHaskell to write such function. This way is hard and rather complex way. The easier way is to use C-preprocessor like this:
{-# LANGUAGE CPP #-}
#define MY_OWN_CLASS (Eq, Ord, Show, Read, Data, SymWord, HasKind, SMTValue)
data X = A | B | C
deriving MY_OWN_CLASS
UPDATE (17.07.2016): ideas & sketch of TH solution
Before introducing sketch of solution I will illustrate why this is harder to do with TH. deriving-clause is not some independent clause, it's a part of data declaration so you can't encode only part inside deriving unfortunately. The general approach of writing any TH code is to use runQ command on brackets to see what you should write in the end. Like this:
ghci> :set -XTemplateHaskell
ghci> :set -XQuasiQuotes
ghci> import Language.Haskell.TH
ghci> runQ [d|data A = B deriving (Eq, Show)|]
[ DataD
[]
A_0
[]
Nothing
[ NormalC B_1 [] ]
[ ConT GHC.Classes.Eq , ConT GHC.Show.Show ]
]
Now you see that type classes for deriving are specified as last argument of DataD — data declaration — constructor. The workaround for your problem is to use -XStadandaloneDeriving extension. It's like deriving but much powerful though also much verbose. Again, to see, what exactly you want to generate, just use runQ:
ghci> data D = T
ghci> :set -XStandaloneDeriving
ghci> runQ [d| deriving instance Show D |]
[ StandaloneDerivD [] (AppT (ConT GHC.Show.Show) (ConT Ghci5.D)) ]
You can use StandaloneDerivD and other constructors directly or just use [d|...|]-brackets though they have more magic but they give you list of Dec (declarations). If you want to generate several declarations then you should write you function like this:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE StandaloneDeriving #-}
module Deriving where
import Language.Haskell.TH
boilerplateAnnigilator :: Name -> Q [Dec]
boilerplateAnnigilator typeName = do
let typeCon = conT typeName
[d|deriving instance Show $(typeCon)
deriving instance Eq $(typeCon)
deriving instance Ord $(typeCon)
|]
Brief tutorial can be found here.
And then you can use it in another file (this is TH limitation called staged restriction: you should define macro in one file but you can't use it in the same file) like this:
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
import Deriving
data X = A | B | C
boilerplateAnnigilator ''X
You should put other type classes you want inside boilerplateAnnigilator function. But this approach only works for non-parametrized class. If you have data MyData a = ... then standalone deriving should look like:
deriving instance Eq a => MyData a
And if you want your TH macro work for parametrized classes as well, then you basically should implement whole logic of GHC compiler by deducing whether type have type variables or not and generate instances depending on that. But this is much harder. I think that the best solution is to just make ticket in GHC compiler and let authors implement such feature called deriving aliases :)

Is it possible to get the Kind of a Type Constructor in Haskell?

I am working with Data.Typeable and in particular I want to be able to generate correct types of a particular kind (say *). The problem that I'm running into is that TypeRep allows us to do the following (working with the version in GHC 7.8):
let maybeType = typeRep (Proxy :: Proxy Maybe)
let maybeCon = fst (splitTyConApp maybeType)
let badType = mkTyConApp maybeCon [maybeType]
Here badType is in a sense the representation of the type Maybe Maybe, which is not a valid type of any Kind:
> :k Maybe (Maybe)
<interactive>:1:8:
Expecting one more argument to ‘Maybe’
The first argument of ‘Maybe’ should have kind ‘*’,
but ‘Maybe’ has kind ‘* -> *’
In a type in a GHCi command: Maybe (Maybe)
I'm not looking for enforcing this at type level, but I would like to be able to write a program that is smart enough to avoid constructing such types at runtime. I can do this with data-level terms with TypeRep. Ideally, I would have something like
data KindRep = Star | KFun KindRep KindRep
and have a function kindOf with kindOf Int = Star (probably really kindOf (Proxy :: Proxy Int) = Star) and kindOf Maybe = KFun Star Star, so that I could "kind-check" my TypeRep value.
I think I can do this manually with a polykinded typeclass like Typeable, but I'd prefer to not have to write my own instances for everything. I'd also prefer to not revert to GHC 7.6 and use the fact that there are separate type classes for Typeable types of different kinds. I am open to methods that get this information from GHC.
We can get the kind of a type, but we need to throw a whole host of language extensions at GHC to do so, including the (in this case) exceeding questionable UndecidableInstances and AllowAmbiguousTypes.
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
import Data.Proxy
Using your definition for a KindRep
data KindRep = Star | KFun KindRep KindRep
we define the class of Kindable things whose kind can be determined
class Kindable x where
kindOf :: p x -> KindRep
The first instance for this is easy, everything of kind * is Kindable:
instance Kindable (a :: *) where
kindOf _ = Star
Getting the kind of higher-kinded types is hard. We will try to say that if we can find the kind of its argument and the kind of the result of applying it to an argument, we can figure out its kind. Unfortunately, since it doesn't have an argument, we don't know what type its argument will be; this is why we need AllowAmbiguousTypes.
instance (Kindable a, Kindable (f a)) => Kindable f where
kindOf _ = KFun (kindOf (Proxy :: Proxy a)) (kindOf (Proxy :: Proxy (f a)))
Combined, these definitions allow us to write things like
kindOf (Proxy :: Proxy Int) = Star
kindOf (Proxy :: Proxy Maybe) = KFun Star Star
kindOf (Proxy :: Proxy (,)) = KFun Star (KFun Star Star)
kindOf (Proxy :: Proxy StateT) = KFun Star (KFun (KFun Star Star) (KFun Star Star))
Just don't try to determine the kind of a polykinded type like Proxy
kindOf (Proxy :: Proxy Proxy)
which fortunately results in a compiler error in only a finite amount of time.

How can I use restricted constraints with GADTs?

I have the following code, and I would like this to fail type checking:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
import Control.Lens
data GADT e a where
One :: Greet e => String -> GADT e String
Two :: Increment e => Int -> GADT e Int
class Greet a where
_Greet :: Prism' a String
class Increment a where
_Increment :: Prism' a Int
instance Greet (Either String Int) where
_Greet = _Left
instance Increment (Either String Int) where
_Increment = _Right
run :: GADT e a -> Either String Int
run = go
where
go (One x) = review _Greet x
go (Two x) = review _Greet "Hello"
The idea is that each entry in the GADT has an associated error, which I'm modelling with a Prism into some larger structure. When I "interpret" this GADT, I provide a concrete type for e that has instances for all of these Prisms. However, for each individual case, I don't want to be able to use instances that weren't declared in the constructor's associated context.
The above code should be an error, because when I pattern match on Two I should learn that I can only use Increment e, but I'm using Greet. I can see why this works - Either String Int has an instance for Greet, so everything checks out.
I'm not sure what the best way to fix this is. Maybe I can use entailment from Data.Constraint, or perhaps there's a trick with higher rank types.
Any ideas?
The problem is you're fixing the final result type, so the instance exists and the type checker can find it.
Try something like:
run :: GADT e a -> e
Now the result type can't pick the instance for review and parametricity enforces your invariant.

Resources