I am wiriting simple application which has functionality of saving/loading its current state.
Save function looks as below:
doSave :: BoardType -> Field -> [Char] -> Bool
doSave board player fileName = do
let x = encodeFile fileName (board :: BoardType, player :: Field)
True -- there will be exception handling
And my load function:
doLoad :: [Char] -> IO (BoardType, Field)
doLoad fileName = decodeFile fileName :: IO (BoardType, Field)
And there's my problem, after loading, I have IO (BoardType, Field) which does not fit my program and other functions which probably should not accept IO parameters. If I have followed this IO escalation, there would be all IOs in my application - is it necessary (or - normal in haskell language)?
And finally - is there a simple way I can get rid of this IO?
It takes a little while to get used to.
Some monads let you extract the "inner value" after some work, but IO never does.
There is no way that e.g. returning the system time can ever be "pure" so any calculations you make with it need to remain wrapped in IO.
However, that doesn't mean most of your code lives in IO-land.
main = do
(bt, fld) <- doLoad "somefilename"
let bResult = doSomethingPureWithBoard bt
let fResult = doSomethingPureWithField fld
let bt2 = updateBoard bt bResult fResult
doSave "someFilename" bt2 fld -- This should also be in IO
You can always call pure functions from IO, just not the other way around. The <- gives you the "unwrapped" values while you are in an IO function. Actually it's passing the results as parameters to the next "statement" - google around "de-sugaring do notation" and similar.
is it necessary (or - normal in haskell language)
Your application will typically have an outer wrapper of IO actions, beginning with main :: IO () and the repeatedly restricted code that has less and less privledges, until you're only dealing with pure code.
Related
I am still a beginner in Haskell, so after reading some writefile tutorials online, I see most of the writefile examples online are used inside the main function (main = IO ())
I am wondering whether it's possible to write a function that writes the results into a file using writefile when it is computed? In some programs (especially games), users might want to stop at a particular points of the game by saving the contents into a .txt file.
For example something like this: (this function does not work, just wondering how to make it work)
concat :: FilePath -> [[a]] -> [a]
concat txt [] = []`
concat txt (xs : xss) = do
y <- xs ++ concat xss
writeFile txt (unlines y)
Thanks:)
The writeFile function has the type FilePath -> String -> IO (), which means that it must run in the IO context.
It doesn't have to run in the main function, but any function that involves IO, including writeFile, will have a return type that involves IO. So you could definitely do something like this:
myFunc :: String -> IO ()
myFunc contents = do
-- do something else
writeFile "foo.txt" contents
-- do more stuff here
You can't, however, call functions that return IO a from pure functions (or, rather, you can't extract the value from the IO container). That's by design; it's how Haskell works, and it's a good thing. If you want to enable users to perform impure actions at arbitrary times, you must design for such a feature. Here's my introduction to pure interactions - that's one place to start.
Yes, you can use writeFile in other places than main, but for a place to qualify, the type IO has to be a part of that place's type signature. (The reason I'm saying place is because main isn't a function, but your concat is a function. And the place you want to look at putting your writeFile call has to be an IO action, which can be the result of a function or not.)
You mentioned saving something related to a game into a .txt file. An example of that could be:
saveGame :: FilePath -> GameState -> IO ()
saveGame gameFile gameState =
writeFile gameFile (serializeGame gameState)
serializeGame :: GameState -> String
serializeGame (GameState ...) = ...
runGame :: GameState -> IO ()
runGame gameState = do
...
if wantsToSaveGame
then saveGame gameFile gameState
else ...
...
runGame updatedGameState
main :: IO ()
main = do
...
runGame initialGameState
In this contrived example, serializeGame would not be a suitable place to call saveGame because it's a pure function, whereas runGame is a self-recursive IO () action capable of affecting files on your file system.
An example of a related IO action that isn't a function could be this one:
resetSaveGame :: IO ()
resetSaveGame =
saveGame defaultGameFile initialGameState
I've created a chess game with Haskell and everything seems to be working. However, I'm trying to define the main function of the program so that each time a move is made (which takes two positions and a board as arguments) the resulting board is kept somewhere, so that it can then be used as an argument for the next move. The code looks something like this.
makeMove :: Position -> Position -> Board -> Board
makeMove pos1 pos2 board = ...
I'm aware of the do notation and have a basic understanding of IO in Haskell, but I'm still unsure on how to proceed.
I'm assuming you want your game to be relatively dynamic and to respond to input, hence the IO question.
I'll give a bit of background theory on imperative style commands and IO interpreted as functions, then look at this in Haskell and finally talk about your case from this point of view.
Some background on imperative commands
If this is stuff you know, apologies, but it might help anyway, or it might help others.
In Haskell, we obviously have no direct mutation of variables. But we can consider a (closely) related idea of 'functions on states' - commands which would, in an imperative paradigm, be seen as mutating variables, can be seen as a 'state transformer': a function which, given one state (of the program, world, whatever) outputs another one.
An example:
Suppose we have a state consisting of a single integer variable a. Use the notation x := y meaning 'assign the value of expression y to the variable x'. (In many modern imperative languages this is written x = y, but to disambiguate with the equality relation = we can use a slightly different symbol.) Then the command (call it C)
a := 0
can be seen as something which modifies the variable a. But if we have an abstract idea of a type of 'states', we can see the 'meaning' of C as a function from states to states. This is sometimes written 〚C〛.
So 〚C〛: states -> states, and for any state s, 〚C〛s = <the state where a = 0>. There are much more complicated state transformers that act on much more complicated kinds of state, but the principle is not more complicated than this!
An important way to make new state transformers from old ones is notated by the familiar semicolon. So if we have state transformers C1 and C2, we can write a new state transformer which 'does C1 and then C2' as C1;C2. This is familiar from many imperative programming languages. In fact, the meaning as a state transformer of this 'concatenation' of commands is
〚C1;C2〛: states -> states
〚C1;C2〛s = 〚C2〛(〚C1〛s)
i.e. the composition of the commands. So in a sense, in Haskell-like notation
(;) : (states -> states) -> (states -> states) -> states -> states
c1 ; c2 = c2 . c1
i.e. (;) is an operator on state-transformers which composes them.
Haskell's approach
Now, Haskell has some neat ways of bringing these concepts directly into the language. Instead of having a distinct type for commands (state modifiers without a type, per se) and expressions (which, depending on the imperative context, may also be allowed to modify the state as well as resulting in a value), Haskell somewhat combines these into one. IO () entities represent pure state modifying actions which don't have a meaning as an expression, and IO a entities (where a is not ()) represent (potential) state modifying actions whose meaning as an expression (like a 'return type') is of type a.
Now, since IO () is like a command, we want something like (;), and indeed, in Haskell, we have the (>>) and (>>=) ('bind operators') which act just like it. We have (>>) :: IO a -> IO b -> IO b and (>>=) :: IO a -> (a -> IO b) -> IO b. For a command (IO ()) or command-expression (IO a), the (>>) operator simply ignores the return if there is one, and gives you the operation of doing the two commands in sequence. The (>>=) on the other hand is for if we care about the result of the expression. The second argument is a function which, when applied to the result of the command-expression, gives another command/command-expression which is the 'next step'.
Now, since Haskell has no 'mutable variables', an IORef a-type variable represents a mutable reference variable, to an a-type variable. If ioA is an IORef a-type entity, we can do readIORef ioA which returns an IO a, the expression which is the result of reading the variable. If x :: a we can do writeIORef ioA x which returns an IO (), the command which is the result of writing the value x to the variable. To create a new IORef a, with value x we use newIORef x which gives an IO (IORef a) where the IORef a initially contains the value x.
Haskell also has do notation which you alluded to, which is a nice syntactic sugar for the above. Simply,
do a; b = a >> b
do v <- e; c = e >>= \v -> c
Your case
If we have some IO entity getAMove :: IO (Position, Position) (which might be a simple parser on some user input, or whatever suits your case), we can define
moveIO :: IORef Board -> IO ()
moveIO board =
readIORef board >>= \currentState -> -- read current state of the board
getAMove >>= \(pos1, pos2) -> -- obtain move instructions
writeIORef board (makeMove pos1 pos2 currentState) -- update the board per makeMove
This can also be written using do notation:
moveIO board = do
currentState <- readIORef board; -- read current state of the board
(pos1, pos2) <- getAMove; -- obtain move instructions
writeIORef board (makeMove pos1 pos2 currentState) -- update the board per makeMove
Then, whenever you need a command which updates an IORef Board based on a call to getAMove you can use this moveIO.
Now, if you make appropriate functions with the following signatures, a simple main IO loop can be devised:
-- represents a test of the board as to whether the game should continue
checkForContinue :: Board -> Bool
checkForContinue state = ...
-- represents some kind of display action of the board.
-- could be a simple line by line print.
displayBoardState :: Board -> IO ()
displayBoardState state = ...
-- represents the starting state of the board.
startState :: Board
-- a simple main loop
mainLoop :: IORef Board -> IO ()
mainLoop board = do
currentState <- readIORef board;
displayState currentState;
if checkForContinue currentState then
do moveIO board; mainLoop board
else return ()
main :: IO ()
main = do
board <- newIORef startState;
mainLoop board
You could use recursion to model state as follows:
main :: IO ()
main = do
let initialBoard = ...
gameLoop initialBoard
gameLoop :: Board -> IO ()
gameLoop board | gameOver board = putStrLn "Game over."
| otherwise = do
print board
move <- askUserToMove
let newBoard = applyMove move board
gameLoop newBoard
Here board is "changed" by computing a new one and recursively calling the game loop.
Consider the code below taken from a working example I've built to help me learn Haskell. This code parses a CSV file containing stock quotes downloaded from Yahoo into a nice simple list of bars with which I can then work.
My question: how can I write a function that will take a file name as its parameter and return an OHLCBarList so that the first four lines inside main can be properly encapsulated?
In other words, how can I implement (without getting all sorts of errors about IO stuff) the function whose type would be
getBarsFromFile :: Filename -> OHLCBarList
so that the grunt work that was being done in the first four lines of main can be properly encapsulated?
I've tried to do this myself but with my limited Haskell knowledge, I'm failing miserably.
import qualified Data.ByteString as BS
type Filename = String
getContentsOfFile :: Filename -> IO BS.ByteString
barParser :: Parser Bar
barParser = do
time <- timeParser
char ','
open <- double
char ','
high <- double
char ','
low <- double
char ','
close <- double
char ','
volume <- decimal
char ','
return $ Bar Bar1Day time open high low close volume
type OHLCBar = (UTCTime, Double, Double, Double, Double)
type OHLCBarList = [OHLCBar]
barsToBarList :: [Either String Bar] -> OHLCBarList
main :: IO ()
main = do
contents :: C.ByteString <- getContentsOfFile "PriceData/Daily/yhoo1.csv" --PriceData/Daily/Yhoo.csv"
let lineList :: [C.ByteString] = C.lines contents -- Break the contents into a list of lines
let bars :: [Either String Bar] = map (parseOnly barParser) lineList -- Using the attoparsec
let ohlcBarList :: OHLCBarList = barsToBarList bars -- Now I have a nice simple list of tuples with which to work
--- Now I can do simple operations like
print $ ohlcBarList !! 0
If you really want your function to have type Filename -> OHLCBarList, it can't be done.* Reading the contents of a file is an IO operation, and Haskell's IO monad is specifically designed so that values in the IO monad can never leave. If this restriction were broken, it would (in general) mess with a lot of things. Instead of doing this, you have two options: make the type of getBarsFromFile be Filename -> IO OHLCBarList — thus essentially copying the first four lines of main — or write a function with type C.ByteString -> OHLCBarList that the output of getContentsOfFile can be piped through to encapsulate lines 2 through 4 of main.
* Technically, it can be done, but you really, really, really shouldn't even try, especially if you're new to Haskell.
Others have explained that the correct type of your function has to be Filename -> IO OHLCBarList, I'd like to try and give you some insight as to why the compiler imposes this draconian measure on you.
Imperative programming is all about managing state: "do certain operations to certain bits of memory in sequence". When they grow large, procedural programs become brittle; we need a way of limiting the scope of state changes. OO programs encapsulate state in classes but the paradigm is not fundamentally different: you can call the same method twice and get different results. The output of the method depends on the (hidden) state of the object.
Functional programming goes all the way and bans mutable state entirely. A Haskell function, when called with certain inputs, will always produce the same output. Simple examples of
pure functions are mathematical operators like + and *, or most of the list-processing functions like map. Pure functions are all about the inputs and outputs, not managing internal state.
This allows the compiler to be very smart in optimising your program (for example, it can safely collapse duplicated code for you), and helps the programmer not to make mistakes: you can't put the system in an invalid state if there is none! We like pure functions.
The exception to the rule is IO. Code that performs IO is impure by definition: you could call getLine a hundred times and never get the same result, because it depends on what the user typed. Haskell handles this using the type system: all impure functions are marred with the IO type. IO can be thought of as a dependency on the state of the real world, sort of like World -> (NewWorld, a)
To summarise: pure functions are good because they are easy to reason about; this is why Haskell makes functions pure by default. Any impure code has to be labelled as such with an IO type signature; this tells the compiler and the reader to be careful with this function. So your function which reads from a file (a fundamentally impure action) but returns a pure value can't exist.
Addendum in response to your comment
You can still write pure functions to operate on data that was obtained impurely. Consider the following straw-man:
main :: IO ()
main = do
putStrLn "Enter the numbers you want me to process, separated by spaces"
line <- getLine
let numberStrings = words line
let numbers = map read numberStrings
putStrLn $ "The result of the calculation is " ++ (show $ foldr1 (*) numbers + 10)
Lots of code inside IO here. Let's extract some functions:
main :: IO ()
main = do
putStrLn "Enter the numbers you want me to process, separated by spaces"
result <- fmap processLine getLine -- fmap :: (a -> b) -> IO a -> IO b
-- runs an impure result through a pure function
-- without leaving IO
putStrLn $ "The result of the calculation is " ++ result
processLine :: String -> String -- look ma, no IO!
processLine = show . calculate . readNumbers
readNumbers :: String -> [Int]
readNumbers = map read . words
calculate :: [Int] -> Int
calculate numbers = product numbers + 10
product :: [Int] -> Int
product = foldr1 (*)
I've pulled logic out of main into pure functions which are easier to read, easier for the compiler to optimise, and more reusable (and so more testable). The program as a whole still lives inside IO because the data is obtained impurely (see the last part of this answer for a more thorough treatment of this argument). Impure data can be piped through pure functions using fmap and other combinators; you should try to put as little logic in main as possible.
Your code does seem to be most of the way there; as others have suggested you could extract lines 2-4 of your main into another function.
In other words, how can I implement (without getting all sorts of errors about IO stuff) the function whose type would be
getBarsFromFile :: Filename -> OHLCBarList
so that the grunt work that was being done in the first four lines of main can be properly encapsulated?
You cannot do this without getting all sorts of errors about IO stuff because this type for getBarsFromFile misses an IO. Probably that's what the errors about IO stuff are trying to tell you. Did you try understanding and fixing the errors?
In your situation, I would start by abstracting over the second to fourth line of your main in a function:
parseBars :: ByteString -> OHLCBarList
And then I would combine this function with getContentsOfFile to get:
getBarsFromFile :: FilePath -> IO OHLCBarList
This I would call in main.
I have the following function:
get :: Chars -> IO Chars
get cs = do
char <- getChar
let (dats, idx) = (curData cs, curIndex cs)
let (x,y:xs) = splitAt idx dats
let replacement = x ++ (ord char) : xs
return $ Chars replacement idx
and I'd like to get a Chars value out of it, not an IO action. I have no idea how to do this, or if it is even possible.
The Chars type is basically just a container:
data Chars = Chars {
curData :: [Int],
curIndex :: Int
-- etc.
}
The specifics aren't that important, I just want to know if there's a way for this function to return a Chars instead of an IO Chars.
If not, how do I pass this as an argument to a function that takes a Chars? I'm kind of new to Haskell I/O, but I don't think I want all of my functions that take Chars as arguments to instead have to take IO Chars as arguments, and then extract and repackage them. It seems unnecessary.
Thanks!
You can't, because that would violate referential transparency.
IO in Haskell is made this way exactly to distinguish between actions whose result and effects may vary depending on the interaction with the environment/user and pure functions whose results are not going to change when you call them with the same input parameters.
In order to pass the result to a pure function taking a Chars in input you have to call your IO action into another IO action, bind the result with the <- operator to a variable and pass it to your pure function. Pseudocode example:
myPureFunction :: Chars -> ...
otherAction :: Chars -> IO ()
otherAction cs = do
myChars <- get cs
let pureResult = myPureFunction myChars
...
If you're new to IO in haskell, you may wish to have a look at the Input and Output chapters in Learn You a Haskell for a Great Good! and Real World Haskell.
There is actually a way to simply get a pure value out of an IO action, but in your case you shouldn't do it, as you're interacting with the environment: the unsafe way is ok only when you can guarantee you're not violating referential transparency.
It's impossible (I lie, there is an extremely unsafe way to cheat your way out of it).
The point is that if any I/O is performed, the behaviour and result of your programme may not depend only on explicit arguments to the used functions, thus that must be declared in the type by having it IO something.
You use the result of an IO a action in a pure function by binding the result in main (or something called from main) and then applying the pure function, binding the result in a let,
cs ::Chars
cs = undefined
main = do
chars <- get cs
let result = pureFunction chars
print result
or, if the function you want to apply to chars has type Chars -> IO b
main = do
chars <- get cs
doSomething chars
I' ve got a problem with Haskell. I have text file looking like this:
5.
7.
[(1,2,3),(4,5,6),(7,8,9),(10,11,12)].
I haven't any idea how can I get the first 2 numbers (2 and 7 above) and the list from the last line. There are dots on the end of each line.
I tried to build a parser, but function called 'readFile' return the Monad called IO String. I don't know how can I get information from that type of string.
I prefer work on a array of chars. Maybe there is a function which can convert from 'IO String' to [Char]?
I think you have a fundamental misunderstanding about IO in Haskell. Particularly, you say this:
Maybe there is a function which can convert from 'IO String' to [Char]?
No, there isn't1, and the fact that there is no such function is one of the most important things about Haskell.
Haskell is a very principled language. It tries to maintain a distinction between "pure" functions (which don't have any side-effects, and always return the same result when give the same input) and "impure" functions (which have side effects like reading from files, printing to the screen, writing to disk etc). The rules are:
You can use a pure function anywhere (in other pure functions, or in impure functions)
You can only use impure functions inside other impure functions.
The way that code is marked as pure or impure is using the type system. When you see a function signature like
digitToInt :: String -> Int
you know that this function is pure. If you give it a String it will return an Int and moreover it will always return the same Int if you give it the same String. On the other hand, a function signature like
getLine :: IO String
is impure, because the return type of String is marked with IO. Obviously getLine (which reads a line of user input) will not always return the same String, because it depends on what the user types in. You can't use this function in pure code, because adding even the smallest bit of impurity will pollute the pure code. Once you go IO you can never go back.
You can think of IO as a wrapper. When you see a particular type, for example, x :: IO String, you should interpret that to mean "x is an action that, when performed, does some arbitrary I/O and then returns something of type String" (note that in Haskell, String and [Char] are exactly the same thing).
So how do you ever get access to the values from an IO action? Fortunately, the type of the function main is IO () (it's an action that does some I/O and returns (), which is the same as returning nothing). So you can always use your IO functions inside main. When you execute a Haskell program, what you are doing is running the main function, which causes all the I/O in the program definition to actually be executed - for example, you can read and write from files, ask the user for input, write to stdout etc etc.
You can think of structuring a Haskell program like this:
All code that does I/O gets the IO tag (basically, you put it in a do block)
Code that doesn't need to perform I/O doesn't need to be in a do block - these are the "pure" functions.
Your main function sequences together the I/O actions you've defined in an order that makes the program do what you want it to do (interspersed with the pure functions wherever you like).
When you run main, you cause all of those I/O actions to be executed.
So, given all that, how do you write your program? Well, the function
readFile :: FilePath -> IO String
reads a file as a String. So we can use that to get the contents of the file. The function
lines:: String -> [String]
splits a String on newlines, so now you have a list of Strings, each corresponding to one line of the file. The function
init :: [a] -> [a]
Drops the last element from a list (this will get rid of the final . on each line). The function
read :: (Read a) => String -> a
takes a String and turns it into an arbitrary Haskell data type, such as Int or Bool. Combining these functions sensibly will give you your program.
Note that the only time you actually need to do any I/O is when you are reading the file. Therefore that is the only part of the program that needs to use the IO tag. The rest of the program can be written "purely".
It sounds like what you need is the article The IO Monad For People Who Simply Don't Care, which should explain a lot of your questions. Don't be scared by the term "monad" - you don't need to understand what a monad is to write Haskell programs (notice that this paragraph is the only one in my answer that uses the word "monad", although admittedly I have used it four times now...)
Here's the program that (I think) you want to write
run :: IO (Int, Int, [(Int,Int,Int)])
run = do
contents <- readFile "text.txt" -- use '<-' here so that 'contents' is a String
let [a,b,c] = lines contents -- split on newlines
let firstLine = read (init a) -- 'init' drops the trailing period
let secondLine = read (init b)
let thirdLine = read (init c) -- this reads a list of Int-tuples
return (firstLine, secondLine, thirdLine)
To answer npfedwards comment about applying lines to the output of readFile text.txt, you need to realize that readFile text.txt gives you an IO String, and it's only when you bind it to a variable (using contents <-) that you get access to the underlying String, so that you can apply lines to it.
Remember: once you go IO, you never go back.
1 I am deliberately ignoring unsafePerformIO because, as implied by the name, it is very unsafe! Don't ever use it unless you really know what you are doing.
As a programming noob, I too was confused by IOs. Just remember that if you go IO you never come out. Chris wrote a great explanation on why. I just thought it might help to give some examples on how to use IO String in a monad. I'll use getLine which reads user input and returns an IO String.
line <- getLine
All this does is bind the user input from getLine to a value named line. If you type this this in ghci, and type :type line it will return:
:type line
line :: String
But wait! getLine returns an IO String
:type getLine
getLine :: IO String
So what happened to the IOness from getLine? <- is what happened. <- is your IO friend. It allows you to bring out the value that is tainted by the IO within a monad and use it with your normal functions. Monads are easily identified because they begin with do. Like so:
main = do
putStrLn "How much do you love Haskell?"
amount <- getLine
putStrln ("You love Haskell this much: " ++ amount)
If you're like me, you'll soon discover that liftIO is your next best monad friend, and that $ help reduce the number of parenthesis you need to write.
So how do you get the information from readFile? Well if readFile's output is IO String like so:
:type readFile
readFile :: FilePath -> IO String
Then all you need is your friendly <-:
yourdata <- readFile "samplefile.txt"
Now if type that in ghci and check the type of yourdata you'll notice it's a simple String.
:type yourdata
text :: String
As people already say, if you have two functions, one is readStringFromFile :: FilePath -> IO String, and another is doTheRightThingWithString :: String -> Something, then you don't really need to escape a string from IO, since you can combine this two functions in various ways:
With fmap for IO (IO is Functor):
fmap doTheRightThingWithString readStringFromFile
With (<$>) for IO (IO is Applicative and (<$>) == fmap):
import Control.Applicative
...
doTheRightThingWithString <$> readStringFromFile
With liftM for IO (liftM == fmap):
import Control.Monad
...
liftM doTheRightThingWithString readStringFromFile
With (>>=) for IO (IO is Monad, fmap == (<$>) == liftM == \f m -> m >>= return . f):
readStringFromFile >>= \string -> return (doTheRightThingWithString string)
readStringFromFile >>= \string -> return $ doTheRightThingWithString string
readStringFromFile >>= return . doTheRightThingWithString
return . doTheRightThingWithString =<< readStringFromFile
With do notation:
do
...
string <- readStringFromFile
-- ^ you escape String from IO but only inside this do-block
let result = doTheRightThingWithString string
...
return result
Every time you will get IO Something.
Why you would want to do it like that? Well, with this you will have pure and
referentially transparent programs (functions) in your language. This means that every function which type is IO-free is pure and referentially transparent, so that for the same arguments it will returns the same values. For example, doTheRightThingWithString would return the same Something for the same String. However readStringFromFile which is not IO-free can return different strings every time (because file can change), so that you can't escape such unpure value from IO.
If you have a parser of this type:
myParser :: String -> Foo
and you read the file using
readFile "thisfile.txt"
then you can read and parse the file using
fmap myParser (readFile "thisfile.txt")
The result of that will have type IO Foo.
The fmap means myParser runs "inside" the IO.
Another way to think of it is that whereas myParser :: String -> Foo, fmap myParser :: IO String -> IO Foo.