Haskell – 126 – altre monadi ancora – 7

Continuo da qui, copio qui.

State
Haskell is a pure language and because of that, our programs are made of functions that can’t change any global state or variables, they can only do some computations and return them results. This restriction actually makes it easier to think about our programs, as it frees us from worrying what every variable’s value is at some point in time. However, some problems are inherently stateful in that they rely on some state that changes over time. While such problems aren’t a problem for Haskell, they can be a bit tedious to model sometimes. That’s why Haskell features a thing called the state monad, which makes dealing with stateful problems a breeze while still keeping everything nice and pure.

When we were dealing with random numbers, we dealt with functions that took a random generator as a parameter and returned a random number and a new random generator.  OOPS! saltato il capitolo perché non sono riuscito a caricare il package; chissà se ora sarò più aggiornato 😐

No, continuo a non trovare Random, salto ancora 😡

Stacks
Say we want to model operating a stack. You have a stack of things one on top of another and you can either push stuff on top of that stack or you can take stuff off the top of the stack. When you’re putting an item on top of the stack we say that you’re pushing it to the stack and when you’re taking stuff off the top we say that you’re popping it. If you want to something that’s at the bottom of the stack, you have to pop everything that’s above it.

We’ll use a list to represent our stack and the head of the list will be the top of the stack. To help us with our task, we’ll make two functions: pop and push. pop will take a stack, pop one item and return that item as the result and also return a new stack, without that item. push will take an item and a stack and then push that item onto the stack. It will return () as its result, along with a new stack. Here goes:

type Stack = [Int]

pop :: Stack -> (Int,Stack)
pop (x:xs) = (x,xs)

push :: Int -> Stack -> ((),Stack)
push a xs = ((),a:xs)

We used () as the result when pushing to the stack because pushing an item onto the stack doesn’t have any important result value, its main job is to change the stack. Notice how we just apply the first parameter of push, we get a stateful computation. pop is already a stateful computation because of its type.

Let’s write a small piece of code to simulate a stack using these functions. We’ll take a stack, push 3 to it and then pop two items, just for kicks. Here it is:

stacks.hs

type Stack = [Int]

pop :: Stack -> (Int,Stack)
pop (x:xs) = (x,xs)

push :: Int -> Stack -> ((),Stack)
push a xs = ((),a:xs)

stackManip :: Stack -> (Int, Stack)
stackManip stack = let
  ((),newStack1) = push 3 stack
  (a ,newStack2) = pop newStack1
  in pop newStack2

We take a stack and then we do push 3 stack, which results in a tuple. The first part of the tuple is a () and the second is a new stack and we call it newStack1. Then, we pop a number from newStack1, which results in a number a (which is the 3) that we pushed and a new stack which we call newStack2. Then, we pop a number off newStack2 and we get a number that’s b and a newStack3. We return a tuple with that number and that stack. Let’s try it out:

*Main> :l stacks
[1 of 1] Compiling Main             ( stacks.hs, interpreted )
Ok, modules loaded: Main.
*Main> stackManip [5,8,2,1]
(5,[8,2,1])

Cool, the result is 5 and the new stack is [8,2,1]. Notice how stackManip is itself a stateful computation. We’ve taken a bunch of stateful computations and we’ve sort of glued them together. Hmm, sounds familiar.

The above code for stackManip is kind of tedious since we’re manually giving the state to every stateful computation and storing it and then giving it to the next one. Wouldn’t it be cooler if, instead of giving the stack manually to each function, we could write something like this:

stackManip = do
  push 3
  a <- pop
  pop

Well, using the state monad will allow us to do exactly this. With it, we will be able to take stateful computations like these and use them without having to manage the state manually.

Prossimamente perché ho appena scoperto cose interessanti su Random 😋

👽

Posta un commento o usa questo indirizzo per il trackback.

Trackback

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: