Below script is intended as an extension of a published and working Pandoc Haskell filter script. What has been added is a call to the shell command curl.
#!/usr/bin/env runhaskell
-- svgtex.hs
import Text.Pandoc.JSON
import System.Process
curl latex = readProcess "curl" ["-d", "type=tex&q=" ++ latex, "http://localhost:16000"] ""
main = toJSONFilter svgtex
where svgtex (Math style latex) = do
svg <- curl latex
return (Math style (svg))
svgtex x = x
However, being completely new to Haskell functional programming, it is not surprising that my script fails with:
Couldn't match expected type `IO Inline' with actual type `Inline'
In the expression: x
In an equation for `svgtex': svgtex x = x
In an equation for `main':
...
Despite having skipped over a number on-line Haskell tutorials and StackExchange Q&As, the concept of monads has still not entirely dawned upon me. Hence, a detailed explanation about all things wrong in above script would be very much appreciated!
The problem lies here:
svgtex x = x
The complier complains that
Couldn't match expected type `IO Inline' with actual type `Inline'
because x is an Inline, while svgtex must return an IO Inline. To inject the x into the IO monad, we can simply use the return function
svgtex x = return x
To fully understand what's going on see any monad tutorial (or LYAH). Roughly put, a value of type IO Inline represents an action that can perform any amount of I/O and finally return a value of type Inline. The return function is used to turn a pure value into a dummy IO action which does not do any I/O, but simply return the result.
Related
This question already has answers here:
How to get normal value from IO action in Haskell
(2 answers)
Closed 1 year ago.
In many imperative programming languages like Java, C or Python we can easily add a print function which can give us information about the intermediate state of the program.
My goal is to find a way to do something like that in Haskell. I want the function which not only computes value but also prints something. The function below is a simplified version of what I want to do. My actual function is too complicated and incomprehensive without context to show it here.
My idea is to have a "pure" Haskell function that has an auxiliary function inside which has [Int] -> IO () -> Int type signature. An IO parameter is initialized in the where clause as a do block. But unfortunately, the do block is not executed, when I run the function in GHCI. The function is compiled successfuly though
module Tests where
-- Function returns the sum of the list and tries to print some info
-- but no IO actually happens
pureFuncWithIO :: [Int] -> Int
pureFuncWithIO [] = 0
pureFuncWithIO nums = auxIOfunc nums (return ())
where
auxIOfunc [] _ = 0
auxIOfunc (n : ns) _ = n + auxIOfunc ns (sneakyIOaction n)
sneakyIOaction n
= do -- Not executed
putStrLn $ "adding " ++ (show n);
return ()
Output in GHCI test:
*Tests> pureFuncWithIO [1,2,3,4,5]
15
Meanwhile, I expected something like this:
*Tests> pureFuncWithIO [1,2,3,4,5]
adding 1
adding 2
adding 3
adding 4
adding 5
15
Is it possible to come up with a way to have IO inside, keeping the return type of the outer-most function, not an IO a flavor? Thanks!
This type signature
pureFuncWithIO :: [Int] -> Int
is promising to the caller that no side effect (like prints) will be observed. The compiler will reject any attempt to perform IO. Some exceptions exist for debugging (Debug.Trace), but they are not meant to be left in production code. There also are some "forbidden", unsafe low-level functions which should never be used in regular code -- you should pretend these do not exist at all.
If you want to do IO, you need an IO return type.
pureFuncWithIO :: [Int] -> IO Int
Doing so allows to weave side effects with the rest of the code.
pureFuncWithIO [] = return 0
pureFuncWithIO (n : ns) = do
putStrLn $ "adding " ++ show n
res <- pureFuncWithIO ns
return (n + res)
A major point in the design of Haskell is to have a strict separation of functions which can not do IO and those who can. Doing IO in a non-IO context is what the Haskell type system was designed to prevent.
Your sneakyIOaction is not executed because you pass its result as a parameter to auxIOfunc, but never use that parameter, and haskell being lazy bastard it is never execute it.
If you try to use said parameter you find out that you can't. It's type not allow you to do anithing with it except combine with other IO things.
There is a way to do what you want, but it is on dark side. You need unsafePerformIO
unsafePerformIO :: IO a -> a
That stuff basically allow you to execute any IO. Tricky thing you have to consume result, otherwise you may end up with haskell skip it due to its laziness. You may want to look into seq if you really want to use it, but don't actually need result.
I would like to allow a user to build a list from a series of inputs in Haskell.
The getLine function would be called recursively until the stopping case ("Y") is input, at which point the list is returned.
I know the function needs to be in a similar format to below. I am having trouble assigning the correct type signatures - I think I need to include the IO type somewhere.
getList :: [String] -> [String]
getList list = do line <- getLine
if line == "Y"
then return list
else getList (line : list)
So there's a bunch of things that you need to understand. One of them is the IO x type. A value of this type is a computer program that, when later run, will do something and produce a value of type x. So getLine doesn't do anything by itself; it just is a certain sort of program. Same with let p = putStrLn "hello!". I can sequence p into my program multiple times and it will print hello! multiple times, because the IO () is a program, as a value which Haskell happens to be able to talk about and manipulate. If this were TypeScript I would say type IO<x> = { run: () => Promise<x> } and emphatically that type says that the side-effecting action has not been run yet.
So how do we manipulate these values when the value is a program, for example one that fetches the current system time?
The most fundamental way to chain such programs together is to take a program that produces an x (an IO x) and then a Haskell function which takes an x and constructs a program which produces a y (an x -> IO y and combines them together into a resulting program producing a y (an IO y.) This function is called >>= and pronounced "bind". In fact this way is universal, if we add a program which takes any Haskell value of type x and produces a program which does nothing and produces that value (return :: x -> IO x). This allows you to use, for example, the Prelude function fmap f = (>>= return . f) which takes an a -> b and applies it to an IO a to produce an IO b.
So It is so common to say things like getLine >>= \line -> putStrLn (upcase line ++ "!") that we invented do-notation, writing this as
do
line <- getLine
putStrLn (upcase line ++ "!")
Notice that it's the same basic deal; the last line needs to be an IO y for some y.
The last thing you need to know in Haskell is the convention which actually gets these things run. That is that, in your Haskell source code, you are supposed to create an IO () (a program whose value doesn't matter) called Main.main, and the Haskell compiler is supposed to take this program which you described, and give it to you as an executable which you can run whenever you want. As a very special case, the GHCi interpreter will notice if you produce an IO x expression at the top level and will immediately run it for you, but that is very different from how the rest of the language works. For the most part, Haskell says, describe the program and I will give it to you.
Now that you know that Haskell has no magic and the Haskell IO x type just is a static representation of a computer program as a value, rather than something which does side-effecting stuff when you "reduce" it (like it is in other languages), we can turn to your getList. Clearly getList :: IO [String] makes the most sense based on what you said: a program which allows a user to build a list from a series of inputs.
Now to build the internals, you've got the right guess: we've got to start with a getLine and either finish off the list or continue accepting inputs, prepending the line to the list:
getList = do
line <- getLine
if line == 'exit' then return []
else fmap (line:) getList
You've also identified another way to do it, which depends on taking a list of strings and producing a new list:
getList :: IO [String]
getList = fmap reverse (go []) where
go xs = do
x <- getLine
if x == "exit" then return xs
else go (x : xs)
There are probably several other ways to do it.
new user, semi-noobie Haskell programmer here. I've been looking through 'Write yourself a Scheme in 48 hours' and it occurred to me that, though it would be extremely unsafe in practice, it would be interesting to see if a Haskell program could 'read' a function.
For example, read "+" :: Num a => a -> a -> a -- (that is the type of (+) )
The above example did not work, however. Any ideas? I know this is a really dumb thing to do in practice, but it would be really cool if it were possible, right?
Haskell is a static and compiled language and you can interpret a string as a function by using Language.Haskell.Interpreter.
A minimal example that reads a binary function with type Int -> Int -> Int is:
import Language.Haskell.Interpreter
import System.Environment (getArgs)
main :: IO ()
main = do
args <- getArgs
-- check that head args exists!
errorOrF <- runInterpreter $ do
setImports ["Prelude"]
interpret (head args) (as::Int -> Int -> Int)
case errorOrF of
Left errs -> print errs
Right f -> print $ f 1 2
You can call this program in this way (here I assume the filename with the code is test.hs):
> ghc test.hs
...
> ./test "\\x y -> x + y"
3
The core of the program is runInterpreter, that is where the interpreter interprets the String. We first add the Prelude module to the context with setImports to make available, for example, the + function. Then we call interpret to interpret the first argument as a function and we use as Int -> Int -> Int to enforce the type.
The result of runInterpreter is a Either InterpretError a where a is your type. If the result is Left then you have an error, else you have your function or value. Once you have extracted it from Right, you can use it as you use a Haskell function. See f 1 2 above, for example.
If you want a more complete example you can check haskell-awk, that is my and gelisam project to implement a awk-like command line utility that use Haskell code instead of AWK code. We use Language.Haskell.Interpreter to interpret the user function.
The general answer is that, no, you cannot. Functions are very "opaque" in Haskell generally—the only way you can analyze them is to apply arguments to them (or use typeclasses to pull information out of the type, but that's different).
This means it's very difficult to create a dynamic function in any sort of specialized or simplified way. The best you can do is embed a parser, interpreter, and serialization/deserialization mechanism to another language and then parse strings of that language and execute them in the interpreter.
Of course, if your interpreted language is just Haskell (such as what you get using the hint package) then you can do what you're looking for.
I have been playing around with Haskell for a bit now but I have not fully grasped how to use third party functions that run inside a Monad. Every time I go back to reading articles about Monads, etc. I get a good understanding but when it comes to applying them to real-world code, I cannot figure why a piece of code does not work. I resort to trial and error and usually get it to compile but I feel I should be able to use them properly the first time without trying to go through my heuristic of changes (try let, <-, liftM, etc.)
So I would like to ask a few questions based on this simple function, which admittedly does a lot of interesting things.
import Text.XML.HXT.Core
import Text.HandsomeSoup
import Data.String.Utils
function h = do
let url = myUrlBuilder h
doc = fromUrl url
res = runX $ doc >>> css "strong" /> getText
--nres = liftM rmSpaceAndBang (res)
res
rmSpaceAndBang ps = map (\x-> replace "!" "" (strip x)) ps
The above code compiles. I have purposefully left out the type declarations as what I thought it should be doesn't compile. So here are my questions.
Why can I not do res <- runX ... and return res that way?
Why should res be inside a let statement and not be bound the result of action? As I understand it, do x <- a1; a2 is equivalent to a1 >>= \x -> a2. How is that different when you let x = a1?
When I used <- I got the following error and if not for my trial and error approach I would not have been able to figure out that I need to use let here.
Couldn't match type `[]' with `IO'
Expected type: IO String
Actual type: [String]
While I focused on res above, my lack of understanding applies to other let statements in the function as well.
How do I find the return type of res?
I couldn't figure out a way to search hackage for getText (hxt seems too big to look through module by module. Probably will try Google site search next time). In the end, I ended up typing up some parts of the code in GHCi and did :t res. It told me it is [String]. Is there a better way to do this?
Since res is of type [String] I thought I will put [String] as the return type for my function. But GHC says it should be IO [String] (compiles). Why did :t give me the wrong information first?
When functions return IO String, what's the best way to use pure functions on them?
Now that I am stuck inside IO [String] I need to use to lift everywhere I do string operations. Is there a better way to do this?
Hopefully I will learn enough from this that I will be able to use right syntax without resorting to blindly trying a few combinations.
Update:
The key piece I was missing was the fact res is not a value but rather an action. So I have 2 choices: one is is my above code with let res = but call it at the end and the other is to do res <- but then do return (res).
The advantage of using res <- is that I can get rid of the liftM as res is now [String] (see #duplode's answer below).
Thanks!
In your code, res is an IO [String]. I do not doubt that you got [String] through GHCi at first, but I believe you tested it with
>>> res <- runX $ doc >>> css "strong" /> getText
>>> :t res
res :: [String]
Which is not equivalent to your code. The difference is that let just binds your IO [String] action without running it, while <- in a do block runs the action and binds the result, in this case a [String].
Now that I am stuck inside IO [String] I need to use to lift
everywhere I do string operations. Is there a better way to do this?
Within a do block, sometimes it is more convenient to write:
res <- runX $ doc >>> css "strong" /> getText
return $ rmSpaceAndBang res
Which is strictly equivalent to using liftM (or fmap):
liftM rmSpaceAndBang $ doc >>> css "strong" /> getText
For a fast answer, let doesn't run anything, it's just makes the lhs as a synonym for rhs.
You actually need a monadic function inside the do for computation be executed.
main = do
let func = print "I need to be called"
print "I don't need to be called"
func
outputs:
"I don't need to be called"
"I need to be called"
So res in your code is not a value, it's a monadic action/function.
Remember that <- is tied to >>=, and requires a a -> m b on the rhs.
let has no requirements.
I have problem with reading from file. Whenever I need to read from a file, I do something like this:
main = do x <- readFile "/tmp/foo.txt"
putStr x
But now I would like the path to be an argument, so I tried the following
main s = do x <- readFile s
putStr x
It doesn't work. I see the following error:
Couldn't match expected type `IO t0'
with actual type `FilePath -> IO ()'
In the expression: main
When checking the type of the function `main'
My homework is to write a program and the program has to contain a main function (because it will be compiled) and argument of call must contain the name of the file. I'm not sure I understand this and I don't know how to proceed. I will grateful for some help.
The Haskell report specifies that the main function always has type IO t, (for some type t which will be ignored) and hence never takes normal function arguments, so this is not the right approach.
You are looking for the function getArgs (for which you have to import the module System.Environment. It returns the arguments passed to your program as a list of Strings.
So your code would look like:
import System.Environment
main = do
args <- getArgs
case args of
[file] -> do
x <- readFile file
putStr x
_ -> putStrLn "Wrong number of arguments"
In Haskell, the arguments are NOT given to the main function because of the way Haskell binds its start up and to remain consistent. You need to use System.Environment.getArgs.
In particular, because Haskell is a pure functional language, main is a monadic action that organizes the side-effect-ful computations performed by the software – the result computed by main is discarded, because in functional languages you are detached from the environment w.r.t. computation and only interact with it as a side-effect.
Example
import System.Environment
main = do x <- getArgs; print x
This will print out whatever you type on the command line.
The Haskell wiki has an excellent tutorial on the topic.