Why can data type not be serialized although it is member of the show class? - haskell

data Mine = Firstname String
| Lastname String
deriving (Show, Serialize)
This does not compile and gives the error
Not in scope: type constructor or class `Serialize'
Why is this not seen as member of the Serialize class although it is member of the Show class. I thought that all members of the Show class should serialize without problems?

That error is saying that the Serialize typeclass is not in scope. You need to import the package that defines the typeclass in order to use it. You probably want:
import Data.Serialize
from the cereal package.

If you do want to automatically derive Serialize for your class, you can do it like this:
{-# LANGUAGE DeriveGeneric #-}
import Data.Serialize (Serialize)
import GHC.Generics (Generic)
data Mine = Firstname String
| Lastname String
deriving (Show, Generic)
instance Serialize Mine

Related

Automatically generating `PersistEntity` for pre-existing types

Motivation: I want to use MongoDB to store data. The persistent library seems to be the only high level Haskell library supporting MongoDB. My project has already defined types representing the rows (documents) of any database.
Typical use of persistent is to define your type via a bit of template Haskell, as such:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
import Control.Monad.IO.Class (liftIO)
mkPersist mongoSettings [persistLowerCase|
Person
name String
age Int
deriving Show
|]
However, I already have significant sized types in code akin to:
newtype Name = Name String deriving (Show, Etc, Etc)
data Person = Person
{ name :: Name, age :: Int } deriving (Show, Etc, Etc)
So ideally I'd get my PersistEntity and maybe even PersistField instances via a slimmed down bit of TH such as:
mkPersistFromType mongoSettings ''Person
However, there is no TH function like mkPersistFromType. Writing the class instances by hand is tedious - they are extremely long. What is the right way forward? Is there a mkPersistFromType somewhere I haven't seen or should I just write that myself?
Note that mkPersist is just a function, and it returns a list of declarations to be added to the source file. So you are free to post-process this declarations and e.g. remove unwanted ones.
Here is an example where I filter out all data declarations:
myMkPersist settings = do
filter wanted <$> mkPersist settings [persistLowerCase|
Person
name String
|]
where
wanted DataD{} = False
wanted _ = True
Note that myMkPersist should be defined in a separate file due to the stage restriction. In the main file you use this function:
data Person = Person
{ personName :: String
}
myMkPersist mongoSettings
Also you may want to check the output on the mkPersist to see how exactly you want to post-process the declarations, you can do that using -ddump-splices cli option.

What is wrong with my data constructor import/use, when ghc suggestion is to add constructor to import list?

I have the following line of code where I'm trying to extract the internal raw type so I can work with it directly:
SDL.Internal.Types.Window (rawWindow) = window
My import looks like:
import qualified SDL.Internal.Types (Window)
The error I get is below; it seems I'm already doing what it suggests.
% /home/brandon/workspace/hico/src/Hico/Game.hs:273:5: error:
Not in scope: data constructor `SDL.Internal.Types.Window'
Perhaps you want to add `Window' to the import list
in the import of `SDL.Internal.Types' (src/Hico/Game.hs:34:1-48).
|
273 | SDL.Internal.Types.Window (rawWindow) = window
| ^^^^^^^^^^^^^^^^^^^^^^^^^
The content of the Types.hs file is very short, and doesn't seem to offer any clues to me:
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module SDL.Internal.Types
( Joystick(..)
, Window(..)
, Renderer(..)
) where
import Data.Data (Data)
import Data.Typeable
import GHC.Generics (Generic)
import qualified SDL.Raw as Raw
newtype Joystick = Joystick { joystickPtr :: Raw.Joystick }
deriving (Data, Eq, Generic, Ord, Show, Typeable)
newtype Window = Window (Raw.Window)
deriving (Data, Eq, Generic, Ord, Show, Typeable)
-- | An SDL rendering device. This can be created with 'SDL.Video.createRenderer'.
newtype Renderer = Renderer Raw.Renderer
deriving (Data, Eq, Generic, Ord, Show, Typeable)
By writing
import qualified SDL.Internal.Types (Window)
you are importing only the type Window, and none of its constructors. To import a data type and some limited subset of its constructors, one writes (using Maybe as an example because I don't know SDL's types):
import Prelude (Maybe(Just))
This import would allow you to use Maybe in type annotations, and use the Just constructor to pattern-match or to create new values of type Maybe a, but you would not be able to use Nothing in either of those circumstances.
Note that the above would be a very unusual thing to do: normally you want either all of a type's constructors (so that you can build and consume any value of that type), or none of them (so that your functions can receive or return values of that type, constructed and consumed by other functions).
If you want all of a type's constructors, you can use the exact syntax used in the module export definition you listed: (..) means "all of the constructors of this type":
import qualified SDL.Internal.Types (Window(..))

(Generically) Build Parsers from custom data types?

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.

Is it possible to construct a new record using Lenses?

If I have a record type with lenses, is it possible to construct a new record without using the underlying record accessors?
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Lens.TH
data Foo = Foo { _s :: String
, _b :: Bool
} deriving (Show, Eq)
makeLenses ''Foo
I could make Foo an instance of Data.Default and then modifiy def with lenses, but not all record types will have sensible defaults. Does Control.Lens have its own way to do it?
No, there is currently no way to do that. You'll have to use something like Foo{} as default or not use lens for record construction. However, there is already an issue in lens covering this.

how to write a derivable class?

i have this
data Something = Something Integer deriving (MyClass, Show)
class MyClass a where
hello :: MyClass a => a -> a
instance MyClass Integer where
hello i = i + 1
main = print . hello $ Something 3
but MyClass isn't derivable. Why?
GHC cannot magically derive instances for arbitrary data types. However, it
can make use of the fact that newtype declarations create a new name for the
same underlying type to derive instances for those using the
GeneralizedNewtypeDeriving extension. So, you could do something like this:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Something = Something Integer deriving (MyClass, Show)
class MyClass a where
hello :: MyClass a => a -> a
instance MyClass Integer where
hello i = i + 1
main = print . hello $ Something 3
The reason GHC cannot derive the new instance is that it does not know what the instance
should be. Even if your data type only has one field, it may not necessarily be the
same as that field. The ability to derive instances for newtypes is convenient, since they
are usually used to provide different behaviours for certain typeclasses or as a way to
use the type system to separate things that have the same type but different uses in your code.
You may want to have a look at the GHC documentation on Generic Programming.
You need to create a class that can work on a generic representation of arbitrary types. I don't think the specific example you gave is reasonable for a derivable class.

Resources