Reputation: 1
I have a list of chars
left = ['h', 'e', 'l', 'l', 'o']
and the function
typer :: [Char] -> Char -> [Char]
typer left c = left ++ [c]
Which seems to work if I type typer left 'a'
into ghci
it returns "helloa"
but if I then try to read left
it returns "hello"
. Where does the "a"
go? is there anyway to manipulate left
using the function?
Upvotes: 0
Views: 1499
Reputation: 1
Not usually, no. Usually, Haskell variables are not mutable. There are however libraries that contain mutable variables. For example, Data.IORef
contains IORef
, which is mutable. I will explain how to use them below, but as a general rule, using I would recommend against it, and instead write your code in a more functional manner.
With IORef, your function typer
can be rewritten
typer :: IORef [Char] -> Char -> IO()
typer left c = writeIORef left . (++[c]) =<< readIORef left
Let us consider its different parts.
readIORef left
pulls out the value "hello"
from the IORef
and wraps it in the IO
monad.f =<< x
takes x
, which is wrapped in a monad, unwraps it and passes it as an argument to f
, but only if we promise that f
returns a value wrapped in the same monad. Here, x
is "hello"
wrapped in IO
and f
is writeIORef left . (++[c])
..
combines the functions writeIORef left
and (++[c])
into one, so that (++[c])
is applied before writeIORef left
.(++[c])
appends the character c
.writeIORef left
returns an empty action wrapped in IO
(IO()
), but it has the side effect that the value of the IORef
left
is modified. Since it returns a value wrapped in IO
, the promise we made to =<<
is fulfilled.With the above function, the code
main :: IO()
main = do x <- newIORef "hello"
typer x 'a'
readIORef x >>= print
should yield the desired effect.
Upvotes: 0
Reputation: 475
Nope! Values in Haskell are immutable.
You have declared your left
to be equal to "hello"
, and it will always be equal to "hello"
. You can hide that particular left
value with some new token called left
in a closer scope (such as having a function argument called left
, which will make the globally defined left
invisible in the function body). There is however no way to change your declared left
value[1].
A new string is returned by typer
, and you have to hold onto that value if you want to hold onto "helloa"
.
[1] In GHCi, you can hide previous definitions by re-defining them. This quietly re-purposes the existing name to point to a new value. You cannot do this in a Haskell source file.
Upvotes: 2
Reputation: 34581
Haskell functions are pure functions, which means they can't have side effects such as modifying variables. Your typer
function computes a result based on its arguments, but it doesn't (and can't) actually modify its arguments.
As an analogy, in mathematics, if n is 4 then sqrt(n) is 2, but n is still 4 even after you've computed its square root.
If you want to capture the result of your function call so you can use it later, assign it to another variable:
right = typer left 'a'
Upvotes: 3