Is it possible to construct a new record using Lenses? - haskell

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.

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

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 :)

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

How to derive instances of Data.Messagepack 1.0.0

The previous version of Data.Messagepack, 0.7.2.5 supports deriving instances via Template Haskell. The current version (1.0.0), however, doesn't.
I was hence wondering if there is an alternative way to automatically derive MessagePack 1.0.0 instances, possibly using XDeriveGeneric?
As a stop-gap measure, have a look at the msgpack-aeson directory of the message-pack github repo:
https://github.com/msgpack/msgpack-haskell/tree/master/msgpack-aeson
You could go from your data values <-> aeson <-> message-pack. Not necessarily efficient, but convenient since you can auto derive ToJSON and FromJSON with DeriveGeneric.
Example code:
{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
import Data.MessagePack.Aeson
import qualified Data.MessagePack as MP
import GHC.Generics
import Data.Aeson
data Foo = Foo { _a :: Int, _b :: String }
deriving (Generic)
instance ToJSON Foo
instance FromJSON Foo
toMsgPack :: Foo -> Maybe MP.Object
toMsgPack = decode . encode
test = toMsgPack (Foo 3 "asd")
You could write your own GMessagePack class and get instances by deriving Generic. I tried doing so to answer this question, but I can't recommend it. msgpack has no support for sums, and the one sum type supported by the Haskell msgpack library, Maybe, has a very poor encoding.
instance MessagePack a => MessagePack (Maybe a) where
toObject = \case
Just a -> toObject a
Nothing -> ObjectNil
fromObject = \case
ObjectNil -> Just Nothing
obj -> fromObject obj
The encoding for Maybes can't tell the difference between Nothing :: Maybe (Maybe a) and Just Nothing :: Maybe (Maybe a), both will be encoded as ObjectNil and decoded as Nothing. If we were to impose on MessagePack instances the obvious law fromObject . toObject == pure, this instance for MessagePack would violate it.

Resources