Haskell read function overloading with two inputs - haskell

In my haskell program I have a list that represents a database in [(key, value)] format. For example this is a valid database: [("key1", "value1"), ("key2", "value2"), ("key3", "value3")]. The key and value data will always have String type.
My question is: is it possible to code the reading operation by overloading the read function and using that in this way: read dbList "key1"? If yes how can I solve this problem? The output needs to be ("not found","value data for key not exists") or ("found", "value1").
I`ve looked up how can I solve this but all that I found is how to use read function to one input parameter and how to define a new type in order to create an instance of the read for that particular type if it is needed. But I am still curious if I can overload somehow the read function with two input paramaters.

The function you want is lookup, which is part of the Prelude.
> :t lookup
lookup :: Eq a => a -> [(a, b)] -> Maybe b
> let dbList = [("key1", "value1")]
> lookup "key1" dbList
Just "value1"
> lookup "key2" dbList
Nothing
If you really need the output in the tuple form you show, you can pattern-match on the result.
case lookup dbList someKey of
Just x -> ("found", x)
Nothing -> ("not found", "data for " ++ key ++ " does not exist")

For completeness, I will present a way to do it using read. However, this is very unusual and I would consider it a bad idea, since you can just use lookup.
{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
type DB = [(String, String)]
instance Read (DB -> (String, String)) where
readsPrec _ = \key -> let
f db = case lookup key db of
Just x -> ("found", x)
Nothing -> ("not found", "data for " ++ key ++ " does not exist")
in [(f, "")]
Here we define an instance of Read for the type DB -> (String, String). Recall that the read function has type Read a => String -> a, so this instance gives us an overload of read of type String -> DB -> (String, String).
Our instance defines the readsPrec function, which has type Read a => Int => ReadS a, where ReadS a is an alias for String -> [(a, String)]. So our readsPrec implementation must have type Int -> String -> [(DB -> (String, String), String)]. We don’t care about the “precedence” argument, so we ignore it with _. And we only care about returning a single result in this instance, so we simply return [(f, "")] where f is a function of type DB -> (String, String) that performs the lookup of the key in its argument db.
Now we can use this instance like so:
> read "foo" [("foo", "bar")] :: (String, String)
("found","bar")
> read "baz" [("foo", "bar")] :: (String, String)
("not found","data for baz does not exist")
Again I would stress that this is an unusual instance that may cause confusion in real code—you should just use lookup directly.

Related

Deserializing many network messages without using an ad-hoc parser implementation

I have a question pertaining to deserialization. I can envision a solution using Data.Data, Data.Typeable, or with GHC.Generics, but I'm curious if it can be accomplished without generics, SYB, or meta-programming.
Problem Description:
Given a list of [String] that is known to contain the fields of a locally defined algebraic data type, I would like to deserialize the [String] to construct the target data type. I could write a parser to do this, but I'm looking for a generalized solution that will deserialize to an arbitrary number of data types defined within the program without writing a parser for each type. With knowledge of the number and type of value constructors an algebraic type has, it's as simple as performing a read on each string to yield the appropriate values necessary to build up the type. However, I don't want to use generics, reflection, SYB, or meta-programming (unless it's otherwise impossible).
Say I have around 50 types defined similar to this (all simple algebraic types composed of basic primitives (no nested or recursive types, just different combinations and orderings of primitives) :
data NetworkMsg = NetworkMsg { field1 :: Int, field2 :: Int, field3 :: Double}
data NetworkMsg2 = NetworkMsg2 { field1 :: Double, field2 :: Int, field3 :: Double }
I can determine the data-type to be associated with a [String] I've received over the network using a tag id that I parse before each [String].
Possible conjectured solution path:
Since data constructors are first-class values in Haskell, and actually have a type-- Can NetworkMsg constructor be thought of as a function, such as:
NetworkMsg :: Int -> Int -> Double -> NetworkMsg
Could I transform this function into a function on tuples using uncurryN then copy the [String] into a tuple of the same shape the function now takes?
NetworkMsg' :: (Int, Int, Double) -> NetworkMsg
I don't think this would work because I'd need knowledge of the value constructors and type information, which would require Data.Typeable, reflection, or some other metaprogramming technique.
Basically, I'm looking for automatic deserialization of many types without writing type instance declarations or analyzing the type's shape at run-time. If it's not feasible, I'll do it an alternative way.
You are correct in that the constructors are essentially just functions so you can write generic instances for any number of types by just writing instances for the functions. You'll still need to write a separate instance
for all the different numbers of arguments, though.
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Text.Read
import Control.Applicative
class FieldParser p r where
parseFields :: p -> [String] -> Maybe r
instance Read a => FieldParser (a -> r) r where
parseFields con [a] = con <$> readMaybe a
parseFields _ _ = Nothing
instance (Read a, Read b) => FieldParser (a -> b -> r) r where
parseFields con [a, b] = con <$> readMaybe a <*> readMaybe b
parseFields _ _ = Nothing
instance (Read a, Read b, Read c) => FieldParser (a -> b -> c -> r) r where
parseFields con [a, b, c] = con <$> readMaybe a <*> readMaybe b <*> readMaybe c
parseFields _ _ = Nothing
{- etc. for as many arguments as you need -}
Now you can use this type class to parse any message based on the constructor as long as the type-checker is able to figure out the resulting message type from context (i.e. it is not able to deduce it simply from the given constructor for these sort of multi-param type class instances).
data Test1 = Test1 {fieldA :: Int} deriving Show
data Test2 = Test2 {fieldB ::Int, fieldC :: Float} deriving Show
test :: String -> [String] -> IO ()
test tag fields = case tag of
"Test1" -> case parseFields Test1 fields of
Just (a :: Test1) -> putStrLn $ "Succesfully parsed " ++ show a
Nothing -> putStrLn "Parse error"
"Test2" -> case parseFields Test2 fields of
Just (a :: Test2) -> putStrLn $ "Succesfully parsed " ++ show a
Nothing -> putStrLn "Parse error"
I'd like to know how exactly you use the message types in the application, though, because having each message as its separate type makes it very difficult to have any sort of generic message handler.
Is there some reason why you don't simply have a single message data type? Such as
data NetworkMsg
= NetworkMsg1 {fieldA :: Int}
| NetworkMsg2 {fieldB :: Int, fieldC :: Float}
Now, while the instances are built in pretty much the same way, you get much better type inference since the result type is always known.
instance Read a => MessageParser (a -> NetworkMsg) where
parseMsg con [a] = con <$> readMaybe a
instance (Read a, Read b) => MessageParser (a -> b -> NetworkMsg) where
parseMsg con [a, b] = con <$> readMaybe a <*> readMaybe b
instance (Read a, Read b, Read c) => MessageParser (a -> b -> c -> NetworkMsg) where
parseMsg con [a, b, c] = con <$> readMaybe a <*> readMaybe b <*> readMaybe c
parseMessage :: String -> [String] -> Maybe NetworkMsg
parseMessage tag fields = case tag of
"NetworkMsg1" -> parseMsg NetworkMsg1 fields
"NetworkMsg2" -> parseMsg NetworkMsg2 fields
_ -> Nothing
I'm also not sure why you want to do type-generic programming specifically without actually using any of the tools meant for generics. GHC.Generics, SYB or Template Haskell is usually the best solution for this kind of problem.

Generic data constructor for Data instance

Given a datatype
data Foo = IFoo Int | SFoo String deriving (Data, Typeable)
what is a simple definition of
gconstr :: (Typeable a, Data t) => a -> t
such that
gconstr (5 :: Int) :: Foo == IFoo 5
gconstr "asdf" :: Foo == SFoo "asdf"
gconstr True :: Foo == _|_
It would be essentially the opposite of syb's gfindtype.
Or does such a thing exist already? I've tried hoogle-ing the type and haven't found much, but the syb types are kind of hard to interpret. A function returning Nothing on error is also acceptable.
This seems to be possible, though it's not completely trivial.
Preliminaries:
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Monad ( msum )
import Data.Data
import Data.Maybe
First a helper function gconstrn, which tries to do the same thing as required of gconstr, but for a specific constructor only:
gconstrn :: (Typeable a, Data t) => Constr -> a -> Maybe t
gconstrn constr arg = gunfold addArg Just constr
where
addArg :: Data b => Maybe (b -> r) -> Maybe r
addArg Nothing = Nothing
addArg (Just f) =
case cast arg of
Just v -> Just (f v)
Nothing -> Nothing
The key part is that the addArg function will use arg as an argument to the constructor, if the types match.
Essentially gunfold starts unfolding with Just IFoo or Just SFoo, and then the next step is to try addArg to provide it with its argument.
For multi-argument constructors this would be called repeatedly, so if you defined an IIFoo constructor that took two Ints, it would also get successfully filled in by gconstrn. Obviously with a bit more work you could do something more sophisticated like providing a list of arguments.
Then it's just a question of trying this with all possible constructors. The recursive definition between result and dt is just to get the right type argument for dataTypeOf, the actual value being passed in doesn't matter at all. ScopedTypeVariables would be an alternative for achieving this.
gconstr :: (Typeable a, Data t) => a -> Maybe t
gconstr arg = result
where result = msum [gconstrn constr arg | constr <- dataTypeConstrs dt]
dt = dataTypeOf (fromJust result)
As discussed in the comments, both functions can be simplified with <*> from Control.Applicative to the following, though it's a bit harder to see what's going on in the gunfold:
gconstr :: (Typeable a, Data t) => a -> Maybe t
gconstr arg = result
where
result = msum $ map (gunfold (<*> cast arg) Just) (dataTypeConstrs dt)
dt = dataTypeOf (fromJust result)

Errorhandling and monads?

I'm trying to understand how to apply the Maybe-idiom from Haskel.. I'm reading http://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe which shows that a lookup in a dictionary may return a Maybe and that this value propates through the >>= operator.
The example from the URL:
If we then wanted to use the result from the governmental database lookup in a third lookup (say we want to look up their registration number to see if they owe any car tax), then we could extend our getRegistrationNumber function:
getTaxOwed :: String -- their name
-> Maybe Double -- the amount of tax they owe
getTaxOwed name =
lookup name phonebook >>=
(\number -> lookup number governmentalDatabase) >>=
(\registration -> lookup registration taxDatabase)
Or, using the do-block style:
getTaxOwed name = do
number <- lookup name phonebook
registration <- lookup number governmentalDatabase
lookup registration taxDatabase
Question:
How do I deal with error handling? I think most code will benefit from telling where things went wrong. Rather than just reporting "couldn't find John Doe in either phonebook or governmentalDatabase" it should report which ressource had problems.
You could use the monad instance for Either String, which is essentially defined as
instance Monad (Either String) where
fail msg = Left msg
return x = Right x
Left msg >>= k = Left msg
Right x >>= k = k x
(The actual definition is a bit more involved.)
If we then define dictionaries as pairs consisting of a label and a lookup table
type Dict a b = (String, [(a, b)])
phonebook' :: Dict String Int
phonebook' = ("phone book", phonebook)
governmentalDatabase' :: Dict Int Int
governmentalDatabase' = ("governmental database", governmentalDatabase)
taxDatabase' :: Dict Int Double
taxDatabase' = ("tax database", taxDatabase)
where phonebook, governmentalDatabase, and taxDatabase are as you had them defined before, we can use an alternative monadic lookup function that returns its result in the Either String-monad:
lookup' :: (Eq a, Show a) => a -> Dict a b -> Either String b
lookup' key (descr, table) = case lookup key table of
Nothing -> Left ("couldn't find " ++ show key ++ " in " ++ descr)
Just val -> Right val
Illustrating the power of monads, the only thing that now needs to change in your client function is the type signature:
getTaxOwed :: String -- their name
-> Either String Double -- either an error message
-- or the amount of tax they owe
getTaxOwed name = do
number <- lookup' name phonebook'
registration <- lookup' number governmentalDatabase'
lookup' registration taxDatabase'
Running this function on an unknown name gives:
> getTaxOwed "Joe"
Left "couldn't find \"Joe\" in phone book"
The Maybe data type has only the value "Nothing" for signaling an error. If you want to return a specific error message i suggest the data type "Either", which can return either a "Left a" or "Right a" value. Read more about how to use that at http://learnyouahaskell.com/for-a-few-monads-more#error

Laziness and polymorphic values

(For the following, simplify Show and Read to
class Show a where show :: a -> String
class Read a where read :: String -> a
And assume that read never fails.)
It's well-known that one can make an existential type of the form
data ShowVal where
ShowVal :: forall a. Show a => a -> ShowVal
And then construct a "heterogeneous list" :: [ShowVal], such as
l = [ShowVal 4, ShowVal 'Q', ShowVal True]
It's also well-known that this is relatively useless, because, instead, one can
just construct a list :: [String], such as
l = [show 4, show 'Q', show True]
Which is exactly isomorphic (after all, the only thing one can do with a
ShowVal is show it).
Laziness makes this particularly nice, because for each value in the list, the
result of show is memoized automatically, so no String is computed more than
once (and Strings that aren't used aren't computed at all).
A ShowVal is equivalent to an existential tuple exists a. (a -> String, a),
where the function is the Show dictionary.
A similar construct can be made for Read:
data ReadVal where
ReadVal :: (forall a. Read a => a) -> ReadVal
Note that, because read is polymorphic in its return value, ReadVal is
universal rather than existential (which means that we don't really need it at
all, because Haskell has first-class universals; but we'll use it here to
highlight the similaries to Show).
We can also make a list :: [ReadVal]:
l = [ReadVal (read "4"), ReadVal (read "'Q'"), ReadVal (read "True")]
Just as with Show, a list :: [ReadVal] is isomorphic to a list :: [String],
such as
l = ["4", "'Q'", "True"]
(We can always get the original String back with
newtype Foo = Foo String
instance Read Foo where read = Foo
Because the Read type class is open.)
A ReadVal is equivalent to a universal function forall a. (String -> a) -> a
(a CPS-style representation). Here the Read dictionary is supplied by the user
of the ReadVal rather than by the producer, because the return value is
polymorphic rather than the argument.
However, in neither of these representations do we get the automatic
memoization that we get in the String representation with Show. Let's say that
read for our type is an expensive operation, so we don't want to compute it
on the same String for the same type more than once.
If we had a closed type, we could do something like:
data ReadVal = ReadVal { asInt :: Int, asChar :: Char, asBool :: Bool }
And then use a value
ReadVal { asInt = read s, asChar = read s, asBool = read s }
Or something along those lines.
But in this case -- even if we only ever use the ReadVal as one type -- the
String will be parsed each time the value is used. Is there a simple way to
get memoization while keeping the ReadVal polymorphic?
(Getting GHC to do it automatically, similarly to the Show case, would be
ideal, if it's somehow possible. A more explicit memoization approach --
perhaps by adding a Typeable constraint? -- would also be OK.)
Laziness makes this particularly nice, because for each value in the list, the result of show is memoized automatically, so no String is computed more than once (and Strings that aren't used aren't computed at all).
This premise is incorrect. There is no magical memo table under the hood.
Laziness means things that aren't needed, aren't computed. It does not mean that all computed values are shared. You still have to introduce explicit sharing (via a table of your own).
Here's an implementation of the more explicit approach; it requires Typeable, because otherwise there'd be nothing to key the memo table on. I based the memoisation code on uglymemo; there might be a way to get this to work with pure memoisation, but I'm not sure. It's tricky, because you have to construct the table outside of the implicit function that any forall a. (Read a, Typeable a) => ... creates, otherwise you end up constructing one table per call, which is useless.
{-# LANGUAGE GADTs, RankNTypes #-}
import Data.Dynamic
import Control.Concurrent.MVar
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import System.IO.Unsafe
data ReadVal where
ReadVal :: { useReadVal :: forall a. (Read a, Typeable a) => a } -> ReadVal
mkReadVal :: String -> ReadVal
mkReadVal s = unsafePerformIO $ do
v <- newMVar HM.empty
return $ ReadVal (readVal v)
where
readVal :: (Read a, Typeable a) => MVar (HashMap TypeRep Dynamic) -> a
readVal v = unsafePerformIO $ do
m <- readMVar v
let r = read s -- not evaluated
let typeRep = typeOf r
case HM.lookup typeRep m of
Nothing -> do
modifyMVar_ v (return . HM.insert typeRep (toDyn r))
return r
Just r' -> return $ fromDyn r' (error "impossible")

Haskell introspecting a record's field names and types

Based on a recent exchange, I've been convinced to use Template Haskell to generate some code to ensure compile-time type safety.
I need to introspect record field names and types. I understand I can get field names by using constrFields . toConstr :: Data a => a -> [String]. But I need more than the field names, I need to know their type. For example, I need to know the names of fields that are of type Bool.
How do I construct a function f :: a -> [(String, xx)] where a is the record, String is the field name and xx is the field type?
The type should be available, along with everything else, in the Info value provided by reify. Specifically, you should get a TyConI, which contains a Dec value, from which you can get the list of Con values specifying the constructors. A record type should then use RecC, which will give you a list of fields described by a tuple containing the field name, whether the field is strict, and the type.
Where you go from there depends on what you want to do with all this.
Edit: For the sake of actually demonstrating the above, here's a really terrible quick and dirty function that finds record fields:
import Language.Haskell.TH
test :: Name -> Q Exp
test n = do rfs <- fmap getRecordFields $ reify n
litE . stringL $ show rfs
getRecordFields :: Info -> [(String, [(String, String)])]
getRecordFields (TyConI (DataD _ _ _ cons _)) = concatMap getRF' cons
getRecordFields _ = []
getRF' :: Con -> [(String, [(String, String)])]
getRF' (RecC name fields) = [(nameBase name, map getFieldInfo fields)]
getRF' _ = []
getFieldInfo :: (Name, Strict, Type) -> (String, String)
getFieldInfo (name, _, ty) = (nameBase name, show ty)
Importing that in another module, we can use it like so:
data Foo = Foo { foo1 :: Int, foo2 :: Bool }
foo = $(test ''Foo)
Loading that in GHCi, the value in foo is [("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])].
Does that give you the rough idea?

Resources