Aliases in Haskell/GHCI - haskell

Is it possible to set aliases in the ghci.conf file?
For example I have alias sbh='cd Desktop/Sandbox/Haskell' in bash.bashrc which lets me quickly jump to the specified folder. Is the same thing possible in ghci by putting an alias in the ghci.conf file?
I already have a few commands in ghci.conf but I would like to have multiple aliases set up to jump to folder locations without having to use :cd home/sandbox/foo/bar all of the time. I cant find anything on google so either its never been considered before or am just missing something very simple.

The :def command can do this:
:def sbh const $ return ":cd Desktop/Sandbox/Haskell"
As you can see it is a little more complicated than just giving a substitution string: It takes a Haskell function of type String -> IO String which the newly defined command applies to its argument string to calculate new commands to run.
Then in GHCI :sbh to invoke.

GHCI macros should give you what you're looking for. See: https://www.haskell.org/ghc/docs/7.6.2/html/users_guide/ghci-commands.html as a reference.
Search for "macros" (or :def, which is the command to define macros). You can put these in the ghci.conf file.
For example (from the same URL indicated above):
Prelude> let mycd d = Directory.setCurrentDirectory d >> return ""
Prelude> :def mycd mycd
Prelude> :mycd ..
I hope this helps.

Possible not exactly what you need, but in case the quick-jumping function suffices try this as a first fix (invoked by :sbh):
:def sbh (\arg -> return ("System.Directory.setCurrentDirectory \"Desktop/Sandbox/Haskell\""))
Your later solution might make use of the arg reference like in:
:def sbh (\arg -> return ("System.Directory.setCurrentDirectory " ++ "\"" ++ args ++ "\""))
Invoke the latter which by :sbh Desktop/Sandbox/Haskell then.

Related

Xmonad: Prompt with output of shell commands as completion options

When I try to put the output of a shell command into an xmonad prompt as a completion option, i.e. as something that can be chosen via the prompt, I keep running compile errors, no matter what I try.
After initially getting a basic custom prompt to work, the following sanity check:
mkXPrompt TestPrompt config (mkComplFunFromList config ["a", compltest) testFun
compltest = do
output <- "b"
return output
This may not be terribly idiomatic Haskell, but it works as expected, it compiles and "a" as well as "b" are available options in the prompt. But I just can't get compltest to return the output of a shell command.
I have extensively looked at the source of all instances of xmonad prompt I could find in xmonad.contrib, and I have also checked here and on other websites for questions regarding similar issues, found a few and read them thoroughly.
The problem is that in all these cases, people are either doing something FAR more complex than what I'm attempting to do, or something that is simply very different. If I was better at Haskell I could probably adapt something for my needs, but so far I have spend several hours cobbling together functions and going from one compile error (usually type errors) to the next, no matter what I tried.
What I could so far gather is that I cannot "extract" a string out of an IO String for security reasons, and so should use liftIO in some way. I have also understood that some of the magic should happen in a do block, and that for Xmonad, runProcessWithInput is supposed to work somewhat better than readProcess. But practically applying this knowledge is a different matter.
Here is a tiny subset of the mass of functions I have tried so far, using the command "date" as an example (i.e. the output of the date command at the time of invoking the prompt should be a completion option in the prompt):
compltest = do
output <- liftIO $ putStrLn $ runProcessWithInput "date" [] ""
return output
compltest = do
output <- liftIO $ runProcessWithInput "date" [] ""
return output
compltest = io $ (runProcessWithInput "date" [] "" >>= readIO)
I guess bind your key to something like this:
do
output <- runProcessWithInput "date" [] ""
mkXPrompt TestPrompt config (mkComplFunFromList config [output]) testFun
Of course there are more interesting things to do with output than making it a singleton list; if f is your favorite String -> [String] function, then replace [output] with (f output) in the last line.

How could i find path to file by his name?

Sooo guys I have to find path to the file by his name
I've found this func. findExecutable but it's not working
F.e:
fileName <- getLine ("file.txt")
filePath <- findExecutable fileName
case filePath of
Nothing -> error "I can't find this file "
Just path -> print path
Even when I input "/home/.../file.txt" It's not working
How can I fix it
The type of func is findExecutable :: String -> IO (Maybe FilePath)
I give to this func "String" I'm check the result with const. case of but all time i'm getting error
This would happen if file.txt is not, in fact, executable.
The documentation for findExecutable specifically states (bold emphasis mine):
On non-Windows platforms, the behavior is equivalent to findFileWith using the search directories from the PATH environment variable and testing each file for executable permissions.
Try giving it the executable permission:
chmod +x /home/.../file.txt
Then try findExecutable again. Should work.
If you're trying to find the file regardless of it being executable or not, take a look at findFile instead.
Keep in mind, however, that, while for executables there is a rough definition of "find" (meaning "find anywhere on PATH"), this concept is generally not defined for regular files. This means that if you want to "find" a file, you have to specify precisely where you'd like to find it. This is what findFile's first parameter is for.

Just and dot in winghci

Why does this work...
Just.(+3) $ 6.7
Just $ truncate 8.9
...but not this?
Just.truncate $ 8.9
I tried resolving truncate to a simple Double -> Int:
let f :: Double -> Int; f = (\ x -> truncate x);
...but that doesn't appear to be the problem...
Just.f $ 5.6
<interactive>:41:1:
Failed to load interface for `Just'
Use -v to see a list of the files searched for.
Many thanks!
When you mean to compose functions, it's better to write f . g than f.g. It's a little more readable, and you avoid a bunch of problems like this one.
When you have something of the form Foo.bar or Foo.Bar in Haskell, it is parsed as a qualified name. That's why Just.f doesn't work: Just isn't a module, so the 'interface' for Just can't be loaded.
Why Just.(+3) does work as intended: (+3) is a right section, not an identifier, so the dot can't be part of a qualified name. The only way to interpret it is to assume that . is an infix application of the operator (.), so it must be Just . (+3).
A dot between a capitalized identifier and another identifier is parsed as a qualified name (eg. Data.Map.insert), so the error is telling you that it couldn't find a module named Just. You can simply add spaces around the dot to fix this.

Haskell - using getOpt to parse arguments, why does ReqArg take multiple Arguments?

I got an argument parser working using getOpt which is great, but I do have one question. When using ReqArg in an option like:
Option ['c'] ["config"] (ReqArg (\f opts -> opts { configFile = f }) "FILE")
"use a custom configuration file"
what does it use that second argument for (in this case, "FILE")? I have not experienced any kind of difference in behavior when specifying another string.
It's for the auto-generated usage message. Same with OptArg. Run usageInfo on your OptDescr list and see what comes back.

Which Monad do I need?

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.

Resources