Choosing an implementation of a function with a given signature - haskell

I want have some piece of code where I want to call a function foo with different implementations of foo residing in different modules.
Like
foo :: String -> IO[String]
module A:
foo :: String -> IO[String]
foo x = whatever
module B:
foo :: String -> IO[String]
foo x = whatever (different)
and then call the appropriate function based on some parameter. I could do with qualified imports:
import qualified ModuleA as A
import qualified ModuleB as B
bar :: String -> String -> IO[String]
bar moduleToChoose x = case moduleToChoose of
"A" -> A.foo x
"B" -> B.foo x
_ -> Uh oh...
This, however basically screams "There is a so much more elegantâ„¢ solution to this but you just don't get it!" Is there a better solution?

Modules aren't first class in Haskell, and so there is no way to use them directly as parameters. In any case, an improvement on your solution would be using a sum type to encode the distinction in a richer and safer way. That can feel pretty natural given meaningful names for modules, types and values (i.e., names that actually reflect what you are trying to do):
import qualified Formatting.Mimsy as Mimsy
import qualified Formatting.Slithy as Slithy
data FormattingStyle = Mimsy | Slithy
foo :: FormattingStyle -> String -> IO [String]
foo style x = case style of
Mimsy -> Mimsy.foo x
Slithy -> Slithy.foo x
You might want to take this a step further and encode the case switch using a type class:
class Fooer a where
foo :: a -> String -> IO [String]
data Mimsy = Mimsy
instance Fooer Mimsy where
foo _ x = undefined -- etc.
data Slithy = Slithy
instance Fooer Slithy where
foo _ x = undefined -- etc.
Another possibility is to use newtype wrappers around String and a Fooable class, akin to Lee Duhem's answer. Either way, using classes for that feels like overkill to me, so I'd stick with the simple sum type solution.
Yet another approach is using records of functions instead of type classes. That, too, is overkill here, though arguably less so than using classes:
data Fooer = Fooer { foo :: String -> IO [String] }
-- Export only mimsy and slithy, and not the Fooer constructor.
mimsy :: Fooer
mimsy = Fooer { foo = Mimsy.foo }
slithy :: Fooer
slithy = Fooer { foo = Slithy.foo }

I would change bar to take the auxiliary funcion directly as a parameter, instead of using a selector parameter.
bar :: (String -> IO [String]) -> String -> IO [String]
Outside the function (possibly in my Main.hs) I would construct the following map:
strategies :: M.Map String (String -> IO [String])
strategies = M.fromList [("A",A.foo), ("B",B.foo)]
This map allows us to decouple the aggregation of the known implementations from the selection of what implementation to use.
The process of looking into the map and constructing the actual bar' :: String -> IO [String] function in which we are interested should be relegated to the outermost layers of your program. That way, dependencies are minimized and "strategy not found" errors are detected sooner.

One possible solution is using user-defined typeclass, like this:
FooClass.hs
module FooClass (FooClass(..)) where
class FooClass a where
bar :: a -> IO [String]
A.hs
module A where
import FooClass
data A = A String deriving (Show)
foo :: A -> IO [String]
foo (A s) = return ["A", s]
instance FooClass A where
bar = foo
B.hs
module B where
import FooClass
data B = B String deriving (Show)
foo :: B -> IO [String]
foo (B s) = return ["B", s]
instance FooClass B where
bar = foo
After all those code, you can use them like this:
t.hs
import FooClass
import A
import B
main = do
a <- bar (A "bar")
b <- bar (B "bar")
putStrLn $ show (a, b)
Testing:
$ runhaskell t.hs
(["A","bar"],["B","bar"])

Related

Haskell: shortcut for type application

I have a call like someFunc #'SomeX #'SomeY .... Is there some aliasing syntax to make it shorter? Something like:
type ??? = #'SomeX #'SomeY
someFunc #??? ...
?
Your example is very vague, but one thing you can do is to redefine someFunc with a more precise type:
someFunc :: a -> b -> a
someFunc x y = x
someFunc' :: Int -> Bool -> Int
someFunc' = someFunc
Then you can use someFunc' whenever you would previously write someFunc #Int #Bool.
Alternatively, if you only really care about that second #'SomeY argument, then you can use the snail: someFunc #_ #'SomeY. In this case the compiler will automatically try to fill in that underscore type application.

Default values in Haskell data types

When you define a class in a object-oriented language it usually sets the default values for the member variables. Is there any mechanism in Haskell to do the same thing in record types? And a follow up question: If we don't know from the very start all the values for a data constructor but we obtain them from IO interaction can we build the type using something like the builder pattern from OOP?
Thanks in advance
A common idiom is to define a default value.
data A = A { foo :: Int , bar :: String }
defaultA :: A
defaultA = A{foo = 0, bar = ""}
This can be then (purely) "updated" later on with real values.
doSomething :: Bool -> A
doSomething True = defaultA{foo = 32}
doSomething False = defaultA{bar = "hello!"}
Pseudocode example:
data Options = O{ textColor :: Bool, textSize :: Int, ... }
defaultOptions :: Options
defaultOptions = O{...}
doStuff :: Options -> IO ()
doStuff opt = ...
main :: IO ()
main = do
...
-- B&W, but use default text size
doStuff defaultOptions{ color = False }
If there are no sensible default values, you can wrap the field values in Maybe.
If you feel adventurous, you can even use a more advanced approach to statically separate "intermediate" options values, which can lack a few fields, from "finalized" ones, which must have all the fields. (I'd not recommend this to Haskell beginners, though.)
Is there any mechanism in Haskell to do the same thing in record types?
What you can do is hide the constructor, and provide a function as constructor instead.
Say for instance we have a list we want to update, together with a revision number, then we can define it as:
data RevisionList a = RevisionList { theList :: [a],
revision :: Int }
deriving Show
Now we can define a function that initializes the BuildList with an initial list:
revisionList :: [a] -> RevisionList a
revisionList xs = RevisionList { theList = xs, revision=0 }
and by hiding the constructor in the module export, we thus hide the possibility to initialize it with another revision than revision 0. So the module could look like:
module Foo(RevisionList(), revisionList)
data RevisionList a = RevisionList { theList :: [a],
revision :: Int }
revisionList :: [a] -> RevisionList a
revisionList xs = RevisionList { theList = xs, revision=0 }
something like the builder pattern from OOP?
We can for instance use a State monad for that. For instance:
module Foo(RevisionList(), revisionList,
increvision, RevisionListBuilder, prefixList)
import Control.Monad.State.Lazy
type RevisionListBuilder a = State (RevisionList a)
increvision :: RevisionListBuilder a ()
increvision = do
rl <- get
put (rl { revision = 1 + revision rl})
prefixList :: a -> RevisionListBuilder a ()
prefixList x = do
rl <- get
put (rl { theList = x : theList rl })
increvision
So we get the RevisionList thus far, perform updates, put the new result back, and increment the revision number.
So now another module can import our Foo, and use the builder like:
some_building :: RevisionListBuilder Int ()
some_building = do
prefixList 4
prefixList 1
and now we can "make" a RevisionList at revision 2 with as final list [1,4,2,5] with:
import Control.Monad.State.Lazy(execState)
some_rev_list :: RevisionList Int
some_rev_list = execState some_building (revisionList [2,5])
So it would look approximately like:
Foo.hs:
module Foo(RevisionList(), revisionList,
increvision, RevisionListBuilder, prefixList)
data RevisionList a = RevisionList { theList :: [a],
revision :: Int }
deriving Show
type RevisionListBuilder a = State (RevisionList a)
revisionList :: [a] -> RevisionList a
revisionList xs = RevisionList { theList = xs, revision=0 }
increvision :: RevisionListBuilder a ()
increvision = do
rl <- get
put (rl { revision = 1 + revision rl})
prefixList :: a -> RevisionListBuilder a ()
prefixList x = do
rl <- get
put (rl { theList = x : theList rl })
increvision
Bar.hs:
import Foo
import Control.Monad.State.Lazy(execState)
some_building :: RevisionListBuilder Int ()
some_building = do
prefixList 4
prefixList 1
some_rev_list :: RevisionList Int
some_rev_list = execState some_building (revisionList [2,5])
So now we have constructed a some_rev_list with the "building" of some_building:
Foo Bar> some_rev_list
RevisionList {theList = [1,4,2,5], revision = 2}
There's already good answers here, so this answer is only meant as a supplement to the fine answers from chi and Willem Van Onsem.
In mainstream object-oriented languages like Java and C#, it's not that a default object is uninitialised; rather, a default object is normally initialised with default values for their types, and it just happens that for reference types, the default is a null reference.
Haskell doesn't have null references, so records can't be initialised with nulls. The most direct translation of objects would be records where every single constituent element is a Maybe. That's not particularly useful, however, but it highlights how hard it is to protect invariants in OOP.
The Builder pattern doesn't solve that problem at all. Any Builder has to start with an initial Builder object, and that object is going to have to have default values as well.
For more details, and lots of examples, I wrote an article series about this. The article series specifically focuses on the Test Data Builder pattern, but you should be able to see how it generalises to the Fluent Builder pattern in general.

Haskell Type Polymorphism -- Mapping to String

I am new to Haskell, so maybe I am missing some fundamental concepts here (or maybe failed to find the appropriate extension). I was wondering if there was a way to optimize or further abstract the following scenario. This code seems very redundant.
Let's say I have the following data classes:
data Person = Person
{ personName :: !String
, personAge :: !Int
} deriving Show
data Dog = Dog
{ dogName :: !String
, dogAge :: !Int
} deriving Show
Let's say I have a service and I'm only concerned with outputing records as strings. In reality, the strings will probably be JSON and the records fetched from the DB, but let's take a simpler case. I basically need a URL token to fetch an appropriate object (say, the string "dog" will get me a Dog, or even just the Haskell "show" string, without expressly declaring it as (value)::Dog).
I have attempted to implement this in several ways...the only thing that seems to work is the following:
data Creature = DogC Dog
| PersonC Person
deriving Show
fromString :: String -> Maybe Creature
fromString "dog" = Just $ DogC $ Dog "muffin" 8
fromString "person" = Just $ PersonC $ Person "John" 22
fromString _ = Nothing
main :: IO ()
main = do
putStrLn $ show $ fromString "dog"
I'm not entirely fond of the new type, nor the list of fromString declarations. And to benefit from the original data declarations, I would probably need to write a similarly tedious expression (eg, "fromCreature") to revert Creature back into my original types. This information might change, so I would probably need TH for a few of the declarations...
Is there a way around some of this? I fiddled with GADTs and classes, but both seemed to be dependent on type- rather than value- based polymorphism (A string identifier tends to cause issues with ambiguous instances). It would be nice to map the constructor to a string (Say, with Data.Map), but constructors often have different kinds.
Update
So, I went with an approach that isn't exactly relevant to the question I had asked, but it may be useful to someone. I did want to maintain some record types, but most didn't add much value and were getting in my way. The steps I had followed went something like:
Use a different/lower-level DB driver, that returns workable types (eg, [ColumnDef] and [[SQLValue]] instead of tuples and records...).
Create ToJSON instances for SQLValue -- most of the types were covered, except a few ByteString types, and I had to handle the conversion of SQLNull to Null. To maintain compatibility with some record types, my default handler looked like: toJSON = genericToJSON defaultOptions { sumEncoding = UnTaggedValue} The untagged value should allow one to read the JSON into defined data types (eg, Dog / Person ) if desired....
Given that column name is accessible from ColumnDef, I wrote an expression that zips [ColumnDef] and [SqlValue] to a list of Aeson-compatible key-value pairs, eg: toJsPairs :: [ColumnDef] -> [SqlValue] -> [(Text,Value)]
Then, I wrote an expression to fetch the JSON from a table name, which more or less serves as my "universal dispatcher." It references a list of authorized tables, so it's less crazy than it might sound.
The code looked a bit like this (using mysql-haskell).
{-# LANGUAGE OverloadedStrings #-}
import qualified Control.Applicative as App
import Database.MySQL.Base
import qualified System.IO.Streams as Streams
import Data.Aeson (FromJSON, ToJSON)
import Data.Aeson.Encode.Pretty (encodePretty)
import Data.Aeson.Types
import Data.Text.Encoding
import Data.String (fromString)
import Data.ByteString.Internal
import qualified Data.ByteString.Lazy.Internal as BLI
import Data.HashMap.Strict (fromList)
appConnectInfo = defaultConnectInfo {
ciUser = "some_user"
, ciPassword = "some_password"
, ciDatabase = "some_db"
}
instance FromJSON ByteString where
parseJSON (String s) = pure $ encodeUtf8 s
parseJSON _ = App.empty
instance ToJSON ByteString where
toJSON = String . decodeUtf8
instance ToJSON MySQLValue where
toJSON (MySQLNull) = Null
toJSON x = genericToJSON defaultOptions
{ sumEncoding = UntaggedValue } x
-- This expression should fail on dimensional mismatch.
-- It's stupidly lenient, but really dimensional mismatch should
-- never occur...
toJsPairs :: [ColumnDef] -> [MySQLValue] -> [(Text,Value)]
toJsPairs [] _ = []
toJsPairs _ [] = []
toJsPairs (x:xs) (y:ys) = (txt x, toJSON y):toJsPairs xs ys
where
-- Implement any modifications to the key names here
txt = decodeUtf8.columnName
listRecords :: String -> IO BLI.ByteString
listRecords tbl = do
conn <- connect appConnectInfo
-- This is clearly an injection vulnerability.
-- Implemented, however, the values for 'tbl' are intensely
-- vetted. This is just an example.
(defs, is) <- query_ conn $ fromString ( "SELECT * FROM `" ++ tbl ++ "` LIMIT 100")
rcrds <- Streams.toList is
return $ encodePretty $ map (jsnobj defs) rcrds
where
jsnobj :: [ColumnDef] -> [MySQLValue] -> Value
jsnobj defs x = Object $ fromList $ toJsPairs defs x
If what you want to consume at the end is json value - it might make sense to
represent result as json value using aeson library:
{-# LANGUAGE DeriveGeneric #-}
import Data.Aeson
import GHC.Generics
data Dog = Dog Int String deriving (Show, Generic)
data Cat = Cat Int String deriving (Show, Generic)
-- here I'm using instance derived with generics, but you can write one by
-- hands
instance ToJSON Dog
instance ToJSON Cat
-- actions to get stuff from db
getDog :: Monad m => Int -> m Dog
getDog i = return (Dog i (show i))
getCat :: Monad m => Int -> m Cat
getCat i = return (Cat i (show i))
-- dispatcher - picks which action to use
getAnimal :: Monad m => String -> Int -> m (Maybe Value)
getAnimal "dog" i = Just . toJSON <$> getDog i
getAnimal "cat" i = Just . toJSON <$> getCat i
getAnimal _ _ = return Nothing
main :: IO ()
main = do
getAnimal "dog" 2 >>= print
getAnimal "cat" 3 >>= print
getAnimal "chupakabra" 12 >>= print
High energy magic version
class Monad m => MonadAnimal m where
-- basically you want something that fetches extra argumets from HTTP or
-- whatevere, perform DB query and so on.
class Animal a where
animalName :: Proxy a -> String
animalGetter :: MonadAnimal m => m a
locateAnimals :: MonadAnimal m => Q [(String, m Value)]
locateAnimals -- implement using TH (reify function is your friend). It should look for
-- all the animal instances in scope and make a list from them with serialized
-- fetcher.
-- with that in place dispatcher should be easy to implement

Sort list of different types

I'd like to sort a list of two different types. To do so I first create a Wrappertype, so I can mappend both types.
Is having a Wrapper type the right way here?
I'm not clear on how do I do the actual sorting if I'd like to sort by the delta key (i.e. fooDelta and barDelta)
The code:
import Data.List (sortBy)
import Data.Monoid
import Data.Ord (comparing)
data Foo = Foo
{ fooLabel :: String
, fooDelta :: Int
} deriving (Show, Eq)
data Bar = Bar
{ barLabel :: String
, barDelta :: Int
, barAnother :: String
} deriving (Show, Eq)
data Wrapper = WFoo Foo | WBar Bar
deriving (Show, Eq)
sortTest :: [Wrapper]
sortTest =
listFoo <> listBar
where
listFoo = [WFoo $ Foo "label1" 0, WFoo $ Foo "label2" 2]
listBar = [WBar $ Bar "label1" 1 "another1"]
A wrapper type is definitely a good way to do this. Since you simply want to sort your wrapped values based on a constituent Int value, you can use Data.List.sortOn.
Define a function which extracts the delta value:
delta :: Wrapper -> Int
delta (WFoo f) = fooDelta f
delta (WBar b) = barDelta b
Then use sortOn like this:
main :: IO ()
main = print $ sortOn delta sortTest
This gives the following output for your example:
[WFoo (Foo {fooLabel = "label1", fooDelta = 0}),WBar (Bar {barLabel = "label1", barDelta = 1, barAnother = "another1"}),WFoo (Foo {fooLabel = "label2", fooDelta = 2})]
Another way to do this is to define an Ord instance for your wrapper type. Then you can simply use sort on your [Wrapper] list.

How to determine data's constructor from foreign code?

In my Haskell program i have an ADT with many constructors:
data MyData = Con1 |
Con2 |
...
Con20
I have an foreign export ccall function, which wraps [MyData] into array of StablePtr's. After calling it i need to determine which constructor have been used to construct each element.
It could be solved this way
foreign export ccall getType :: StablePtr MyData -> IO CInt
getType (Con1) = return 1
getType (Con2) = return 2
...
but then i would need to manually define these constants in C header. This is error-prone, so i wonder if there is a way to make GHC do this job for me.
deriving Enum for your Haskell type, and export fromEnumMyData :: MyData -> Int ; fromEnumMyData = fromEnum.
Then you can do case analysis on the C side by looking at the Int tag GHC assigns.
I've found solution for this.
I've defined possible constructor types as enum in my C code:
typedef enum
{
MyDataCon1,
MyDataCon2,
...
MyDataCon20
} MyDataConstructor;
Then i used C->Haskell enum hook in my Haskell source:
{#enum MyDataConstructor deriving (Show) #}
After preprocessing this line turns to
data MyDataConstructor = MyDataCon1
| MyDataCon2
...
| MyDataCon20
Now i can define getType this way:
foreign export ccall getType :: StablePtr MyData -> IO CInt
getType md = do
md' <- deRefStablePtr md
case md' of
Con1 -> return $ fromEnum MyDataCon1
Con2 -> return $ fromEnum MyDataCon2
...
Con20 -> return $ fromEnum MyDataCon20

Resources