I'm learning functional programming and try to apply its ideas in day job with imperative languages. My favourite idea is data immutability. I can apply this concept in my programs and try to make all my data structures and model objects immutable. But I have a standard feature in my app: edit user profile. So, I got profile data from the server and create an immutable domain model of it: class
UserProfile and show its info to the user. User can edit any fields: change name, surname, age, interests, whatever. The first idea is to make
UserProfile global, mutable and create a setter for each field. But I want to handle this logic in a pure functional way.
So, what are the possible ways of handling this logic correctly in a functional way?
Best How To :
You might find the
Updatable type from
mvc-updates useful. The basic idea is that you build an
Updatable value by supplying a concurrent input (i.e. a
Controller) and a
Fold over that input:
on :: Fold e a -> Managed (Controller e) -> Updatable a
Here are two example inputs:
lastLine :: Updatable (Maybe String)
lastLine = on last stdinLines
seconds :: Updatable Int
seconds = on length (tick 1.0)
Then you can combine them into larger
Updatable values using
data Example = Example (Maybe String) Int deriving (Show)
example :: Updatable Example
example = Example <$> lastLine <*> seconds
That produces an
Updatable record that updates whenever one of its fields updates.
Finally, you can attach a listener to an
Updatable value using
listen :: (a -> IO ()) -> Updatable a -> Updatable a
... and you can set things in motion using
runUpdatable :: Updatable a -> IO ()
So the full example would be:
main = runUpdatable (listen print example)
... and it will behave like this:
example : Example Nothing 0
example : Example (Just "Test") 0
example : Example (Just "Test") 1
example : Example (Just "Test") 2
lastLine: Just "ABC"
example : Example (Just "ABC") 2
example : Example (Just "ABC") 3
Every time you type a new line of input the left field updates and every time a second passes the right field updates. Each update triggers the listener, which in this case is just
You can learn more by reading the mvc-updates documentation.