Store a variable inside another function in Haskell

I am lost in this concept. This is my code, and what it does is just asking what your name is.

askName = do name <- getLine return () main :: IO () main = do putStrLn "Greetings once again. What is your name?" askName 

However, how can I access in my main variable name made in askName?

This is my second attempt:

 askUserName = do putStrLn "Hello, what your name?" name <- getLine return name sayHelloUser name = do putStrLn ("Hey " ++ name ++ ", you rock!") main = do askUserName >>= sayHelloUser 

Now I can reuse name in the callback, but if in the main I want to call the name again, how can I do this? (avoiding putting name <- getLine basically, obviously)

+1
source share
2 answers

We can imagine that you are asking for a name to print it out and then rewrite it.
In pseudo code, we have

 main = print "what is your name" bind varname with userReponse print varname 

Then your question is about the second instruction.
Take a look at the semantics of this.

  • userReponse is a function that returns user input (getLine)
  • varname is var
  • binding var with fun: this is a function that binds var (varname) to the output of the function (getLine)

Or, as you know, in haskell all this is a function, then our semantics are not very suitable.
We need to revise it to respect this idiom. According to a later reflection, the semantics of our binding become binding fun to fun

Since we cannot have a variable, pass an argument to a function, we need, at first glance, to call another function to produce them. So we need a way to connect the two functions, and that is what bind should do. In addition, as follows from our example, the evaluation order should be followed, and this will lead us to the next rewrite with fun bind fun

This means that the binding is more than the function that it performs. Then for all functions f and g we have f bind g.
In haskell, we mark this as follows

 f >>= g 

Also, since we know that a function takes 0, 1 or more arguments and returns 0, 1 or more arguments.
We could clarify our definition of our bind statement.
In fact, when f returns no result, mark β†’ = as β†’
By applying, theses of reflexes to our pseudo-code lead us to

 main = print "what your name" >> getLine >>= print 

Wait a minute. How does a snap operator differ from using a point operator for a composition of two functions?

It is very different because we omit important information; binding does not connect two functions, but a whole chain of calculations . And the thing is to understand why we defined this operator.

Record the global calculation as a unit sequence.

 f0 >>= f1 >> f2 >> f3 ... >>= fn 

At this stage, global computation can be defined as a set of computations with two operators β†’ = , β†’ .

How do we present a set in computer science?
Usually a container .

Then global computing is a container which contains several units of calculation . On this container, we could define some operator that allows us to move from the unit of calculation to the next, taking into account or not the result later, this is our β†’ = and β†’ .

As a container, we need a way to insert a value, this is done using the return function. Which take the object and enter it into the calculation , you can check it through the signature.

 return :: a -> ma -- m symbolize the container, then the global computation 

Like this calculation , we need a way to manage the failure, which is performed by the fail function.
Actually the calculation interface is defined by the class

 class Computation return -- inject an objet into a computation >>= -- chain two computation >> -- chain two computation, omitting the result of the first one fail -- manage a computation failure 

Now we can refine our code by following

 main :: IO () main = return "What your name" >>= print >> getLine >>= print 

Here, I intentionally include the signature of the main function to express the fact that we are in the global IO calculation, and the result is with () (as an exercise, enter $: t print in ghci).
If we pay more attention to the definition for β†’ = , we can derive the following syntax

 f >>= g <=> f >>= (\x -> g) and f >> g <=> f >>= (\_ -> g) 

And then write

 main :: IO () main = return "what your name" >>= \x -> print x >>= \_ -> getLine >>= \x -> print x 

As you should suspect, we certainly have special syntax for working with the bind operator in a computing environment. You are right, this is the purpose of the do syntax
Then our previous code will become, with do syntax

 main :: IO () main = do x <- return "what your name" _ <- print xx <- getLine print x 

If you want to know more, see monad


As mentioned earlier, my initial conclusion was a bit enthusiastic

You should be shocked because we have a gap of referential transparency (x takes two different values ​​inside our sequence of commands), but it doesn’t matter anymore, because we are in the calculation , and the calculation , as defined below, is the container from which we can get an interface, and this interface is designed to control, as you can explain, the unclean world, which corresponds to the real world.

+6
source

Return the name from askname. In Haskell, its not idiomatic for accessing "global" variables:

 askName :: IO String askName = do name <- getLine return name main :: IO () main = do putStrLn "Greetings once again. What is your name?" name <- askName putStrLn name 

Now the only problem is that the askName function is pointless, since now it is simply an alias of getLine . We could β€œfix” this by asking the question inside askName:

 askName :: IO String askName = do putStrLn "Greetings once again. What is your name?" name <- getLine return name main :: IO () main = do name <- askName putStrLn name 

Finally, there are only two small dots: it’s usually a good idea to put in declarations like when you are learning, make things explicit and help compiler error messages. Another thing to remember is that the "return" function is used only for monadic code (this does not look like the traditional return statement!), And sometimes we could manipulate some intermediate variables:

 askName :: IO String askName = do putStrLn "Greetings once again. What is your name?" getLine 
+3
source

All Articles