Which Monad do I need? - haskell

This is something of an extension to this question:
Dispatching to correct function with command line arguments in Haskell
So, as it turns out, I don't have a good solution yet for dispatching "commands" from the command line to other functions. So, I'd like to extend the approach in the question above. It seems cumbersome to have to manually add functions to the table and apply the appropriate transformation function to each function so that it takes a list of the correct size instead of its normal arguments. Instead, I'd like to build a table where I'll add functions and "tag" them with the number of arguments it needs to take from the command line. The "add" procedure, should then take care of composing with the correct "takesXarguments" procedure and adding it to the table.
I'd like to be able to install "packages" of functions into the table, which makes me think I need to be able to keep track of the state of the table, since it will change when packages get installed. Is the Reader Monad or the State Monad what I'm looking for?

No monad necessary. Your tagging idea is on the right track, but that information is encoded probably in a different way than you expected.
I would start with a definition of a command:
type Command = [String] -> IO ()
Then you can make "command maker" functions:
mkCommand1 :: (String -> IO ()) -> Command
mkCommand2 :: (String -> String -> IO ()) -> Command
...
Which serves as the tag. If you don't like the proliferation of functions, you can also make a "command lambda":
arg :: (String -> Command) -> Command
arg f (x:xs) = f x xs
arg f [] = fail "Wrong number of arguments"
So that you can write commands like:
printHelloName :: Command
printHelloName = arg $ \first -> arg $ \last -> do
putStrLn $ "Hello, Mr(s). " ++ last
putStrLn $ "May I call you " ++ first ++ "?"
Of course mkCommand1 etc. can be easily written in terms of arg, for the best of both worlds.
As for packages, Command sufficiently encapsulates choices between multiple subcommands, but they don't compose. One option here is to change Command to:
type Command = [String] -> Maybe (IO ())
Which allows you to compose multiple Commands into a single one by taking the first action that does not return Nothing. Now your packages are just values of type Command as well. (In general with Haskell we are very interested in these compositions -- rather than packages and lists, think about how you can take two of some object to make a composite object)
To save you from the desire you have surely built up: (1) there is no reasonable way to detect the number of arguments a function takes*, and (2) there is no way to make a type depend on a number, so you won't be able to create a mkCommand which takes as its first argument an Int for the number of arguments.
Hope this helped.
In this case, it turns out that there is, but I recommend against it and think it is a bad habit -- when things get more abstract the technique breaks down. But I'm something of a purist; the more duct-tapey Haskellers might disagree with me.

Related

Haskell multiple actions within pattern match

For a game I want to use animations, for that I want to pick a picture from a list, and then go to the next picture. However, for that I would need to do two things within one function which is not possible I think.
getPicture :: [IO Picture] -> Int -> IO Picture
getPicture a i | i < length a = (!!) i a && getPicture a (i+1)
| otherwise = (!!) i a && getPicture a (0)
Obviously I cannot use && to proceed to the next part, but I was wondering if there was a possibility to do this?
Seeing as you're always recursively calling getPicture, it looks to me like you just want all the pictures in order. You also have a base case which goes back to the first picture. Don't you think getPictures :: [IO Picture] -> IO [Picture] looks like a more suitable signature? It would just get all pictures in a sequence, no need to manually keep track of i.
Luckily there's sequence from Control.Monad which can do exactly this for you. We'll throw in a cycle which accommodates the "go back to the beginning" part.
do
pictures <- cycle <$> sequence getPictures
… -- animate the pictures as you wish
Of course I'm just guessing what you might actually want. For example, this will keep all the pictures (frames?) loaded in memory.

Implementing another kind of flags in Haskell

We have the classic flags in the command line tools, those that enable something (without arguments, e.g --help or --version) and others kind of flags that accept arguments (e.g. --output-dir=/home/ or --input-file="in.a", whatever).
But this time, I would like to implement the following kind of.
$ myprogram --GCC-option="--stdlib 11" --debug
In a general way, the flag is like "--PROGRAM-option=ARGUMENT". Then, I keep from this flag, PROGRAM and ARGUMENT values, they are variables. In the example above, we have PROG=GCC and ARGUMENT=--stdlib 11.
How should can I implement this feature in Haskell? I have some experience parsing options in the classic way.
In a recent project of mine I used an approach based on a 'Data.Tree' of option handling nodes. Of course, I haven't released this code so it's of very limited use, but I think the scheme might be helpful.
data OptHandle = Op { optSat :: String -> Bool
, opBuild :: [String] -> State Env [String]
}
The node fields: check to see if the argument satisfied the node; and incrementally built up an initial program environment based on the the remaining arguments (returning unused arguments to be processed by nodes lower in the tree.)
An option processing tree is then hard coded, such as below.
pgmOptTree :: [Tree OptHandle]
pgmOptTree = [mainHelpT,pgmOptT,dbgT]
mainHelpT :: Tree OptHandle
mainHelpT = Node (Op sat bld) []
where
sat "--help" = True
sat _ = False
bld _ = do
mySetEnvShowHelp
return []
pgmOptT :: Tree OptHandle
pgmOptT = Node (Op sat bld) [dbgT]
where
sat = functionOn . someParse
bld ss = do
let (d,ss') = parsePgmOption ss
mySetEnvPgmOpt d
return ss'
You will also need a function which feeds the command line arguments to the tree, checking satisfiability of each node in a forest, executing the opBuild, and calling subforests. After running the handler in the state monad, you should be returned an initial starting environment which can be used to tell main the functionality you want to call.
The option handler I used was actually a little more complicated than this, as my program communicated with Bash to perform tab completions, and included help for most major options. I found the benefit to the approach was that I could more easily keep in sync three command line concerns: enabling tab completions which could inform users the next available commands; providing help for incomplete commands; and actually running the program for complete commands.
Maintaining a tree like this is nice because you can reuse nodes at different points, and add options that work with the others fairly easily.

How to introspect an Haskell file to get the types of its definitions

I have many files that must be processed automatically. Each file holds the response of one student to an exercise which asks the student to give definitions for some functions given a type for each function.
My idea is to have an Haskell script that loads each student file, and verifies if each function has the expected type.
A constraint is that the student files are not defined as modules.
How can I do this?
My best alternative so far is to spawn a GHCi process that will read stdin from a "test file" with GHCi commands, for example:
:load student1.hs
:t g
... and so on ...
then parse the returned output from GHCi to find the types of the functions in the student file.
Is there another clean way to load an arbitrary Haskell file and introspect its code?
Thanks
Haskell does not save type information at runtime. In Haskell, types are used for pre-runtime type checking at the static analysis phase and are later erased. You can read more about Haskell's type system here.
Is there a reason you want to know the type of a function at runtime? maybe we can help with the problem itself :)
Edit based on your 2nd edit:
I don't have a good solution for you, but here is one idea that might work:
Run a script that for each student module will:
Take the name of the module and produce a file Test.hs:
module Test where
import [module-name]
test :: a -> b -> [(b,a)]
test = g
run ghc -fno-code Test.hs
check the output does not contain type errors
write results into a log file
I think if you have a dynamically determined number of .hs files, which you need to load, parse and introspect, you could/should use the GHC API instead.
See for example:
Using GHC API to compile Haskell sources to CORE and CORE to binary
https://mail.haskell.org/pipermail/haskell-cafe/2009-April/060705.html
These might not be something you can use directly — and I haven't done anything like this myself so far either — but these should get you started.
See also:
https://wiki.haskell.org/GHC/As_a_library
https://hackage.haskell.org/package/hint
The closest Haskell feature to that is Data.Typeable.typeOf. Here's a GHCi session:
> import Data.Typeable
> typeOf (undefined :: Int -> Char)
Int -> Char
> typeOf (undefined :: Int -> [Char])
Int -> [Char]
> typeOf (undefined :: Int -> Maybe [Char])
Int -> Maybe [Char]
> :t typeOf
typeOf :: Typeable a => a -> TypeRep
Under the hood, the Typeable a constraint forces Haskell to retain some type tags until runtime, so that they can be retrieved by typeOf. Normally, no such tags exist at runtime. The TypeRep type above is the type for such tags.
That being said, having such information is almost never needed in Haskell. If you are using typeOf to implement something, you are likely doing it wrong.
If you are using that to defer type checks to run time, when they could have been performed at compile time, e.g. using a Dynamic-like type for everything, then you are definitely doing it wrong.
If the function is supposed to be exported with a specific name, I think probably the easiest way would be to just write a test script that calls the functions and checks they return the right results. If the test script doesn't compile, the student's submission is incorrect.
The alternative is to use either the GHC API (kinda hard), or play with Template Haskell (simpler, but still not that simple).
Yet another possibility is to load the student's code into GHCi and use the :browse command to dump out everything that's exported. You can then grep for the term you're interested in. That should be quite easy to automate.
There's a catch, however: foo :: x -> x and foo :: a -> a are the same type, even though textually they don't match at all. You might contemplate trying to normalise the variable names, but it's worse: foo :: Int -> Int and foo :: Num x => x -> x don't look remotely the same, yet one type is an instance of the other.
...which I guess means I'm saying that my answer is bad? :-(

Function names with symbol characters makes Googling difficult

In Haskell, many function names contain only symbol characters. Like $$, >>=, >>, :, ->, =>, =~.
Since I am new to Haskell, I am finding it difficult to search their meanings in Google. For example, to understand what -> means in Haskell, I need to use the search string hyphen followed by greater than which is not the best approach, as per me.
Is there a place that I could search for functions with symbols only?
Yes, this is a known bug with Google. You might consider a better search engine like Hoogle.
In general you need to look up the documentation for the actual function. To do this, you need to know what module it's defined in. The easiest way to determine this is to load up your source file in GHCi (so that you have all of its imports etc.) and then ask for the operator's :info thusly:
Prelude> :info (>>=)
class Monad (m :: * -> *) where
(>>=) :: m a -> (a -> m b) -> m b
...
-- Defined in ‘GHC.Base’
infixl 1 >>=
Prelude>
If the type signature is not enough, then this also tells you that you need to google the GHC.Base module, and the Monad typeclass. By itself that's pretty googleable, but if that typeclass keyword weren't there, what you would do is to google GHC.Base, the first result leading to the base package overview page. Once you are there1 then you look for a little link labeled [Index] beneath the module listing (GHC.Base has a huge module listing so in this case it's easier to miss).
Clicking that link takes you to an index of all the public symbols in that package; you can click the > character to find all operators beginning with a greater than sign. You will then have three links of modules which export that function; click on one and Ctrl-F to find the following documentation:
(>>=) :: forall a b. m a -> (a -> m b) -> m b | infixl 1 | Source
Sequentially compose two actions, passing any value produced by the first
as an argument to the second.
Again, Hoogle does all of this rigamarole for you and has some other nifty features like searching-by-type-signature.
For things like <-, ->, and => which are not functions, you will just have to know the language. The meaning of <- ("from") is from "do-notation", which you can Google; the meaning of -> ("to") varies depending on whether it appears in lambda-notation (like \a b -> b), case-expressions, or the type signature of a function (where a -> b -> c means "a function which takes an a and returns a function which takes a b and returns some c". The meaning of => is from "constraints" or "type classes" in Haskell.
Other than ->, you can sometimes see operators appearing in type signatures, too. These should be searchable by the above procedure.
This is assuming a stable API for the package. If the API has changed you will need to look up with ghc -v which package version the file is using, then click on that version.

Printing Text.Pandoc.writers into ghci : No Show instance

What am I trying to do ?
Print under ghci the association list of formats and writers.
See doc :
writers :: [(String, Writer)]
Association list of formats and writers.
What has been tried
zurgl>>>import Text.Pandoc as P
zurgl>>>P.writers
<interactive>:20:1:
No instance for (Show (WriterOptions -> Pandoc -> [Char]))
arising from a use of `print'
Possible fix:
add an instance declaration for
(Show (WriterOptions -> Pandoc -> [Char]))
In a stmt of an interactive GHCi command: print it
I expected the corresponding show instance to be imported automatically, but it seems that's not the case. And I must admit I don't have any clue how to define an instance declaration for (Show (WriterOptions -> Pandoc -> [Char]). As a workaround, I've tried to import additional module of the Pandoc library, but still no Show instance available.
Then Should I define this instance by myself ?
If yes, have you any tips to share with me to complete this task.
If I shouldn't what's the issue ?
Thanks in advance for your help.
EDIT
Ok, I guess I saw my missunderstanding :
Doing :
zurgl>>>map (\x-> fst x) P.writers
["native","json","html","html5","html+lhs","html5+lhs","s5","slidy","slideous","dzslides","docbook","opendocument","latex","latex+lhs","beamer","beamer+lhs","context","texinfo","man","markdown","markdown+lhs","plain","rst","rst+lhs","mediawiki","textile","rtf","org","asciidoc"]
I think it make no sens to try to Show the second stuff in my tuples. It souhld be something like a function then we can't show it.
I guess it should be the problem.
What I tried to do make no sense as the tuple contain two different type.
The first one being an identifier (of type string) for a specific writer, the second one being the writer itself (then a function). For sure, if I try to print all of them it will fail as there is no Show instance for function.
Then to retrieve the list of available writer in Pandoc (with the aims to call the corresponding function dynamically), we just have to retrieve the list of identifier, as :
zurgl>>>map fst P.writers
["native","json","html","html5","html+lhs","html5+lhs","s5","slidy","slideous","dzslides","docbook","opendocument","latex","latex+lhs","beamer","beamer+lhs","context","texinfo","man","markdown","markdown+lhs","plain","rst","rst+lhs","mediawiki","textile","rtf","org","asciidoc"]

Resources