I'm having a hard time finding out how to make something change every time the user interacts with my program. It's hard to explain so here's an example (Haskell + wxhaskell):
simulate :: Int -> Frame () -> IO ()
simulate qNr window = do
fdata <- readFile "qarchive"
case (split (listTake (split fdata '\n') qNr 0) '#') of
(qst:a:b:c:coralt:answer:x) -> do
-- GUI Controls Initialization (buttons,text,etc...)
nextButton <- button window [text := "Next Question ->", on command := set infoField [text := "Next Question"], position := pt 185 155]
return ()
main :: IO ()
main = start gui
gui :: IO ()
gui = do
window <- frame [text := "Question program", clientSize := sz 640 480]
headerText <- staticText window [text := "Title Text", fontSize := 20, position := pt 5 5]
simulate 0 window
return ()
I want some widgets to change when the "Next Question" button is pressed. I want to change these widgets to some values I read from a file. How can I keep track of what the current question number is? I cannot actually increment questionNumber as a variable, since Haskell doesn't permit such things. I guess there's another way to do it.
Example:
Initialize GUI
Read data from file
If button is pressed, increment question number by 1 and change widgets.
How do you tackle this kind of problem in a functional manner?
The arguments to functions are your variables. As the user enters new values, pass those values to functions.
For example, a simple program that updates a value based on user input:
main = loop 0
loop n = do
print n
v <- read `fmap` getLine
loop (n + v)
Note the recursive calls to 'loop' have a different value passed each time, based on what the user provided.
This is a fundamental way of thinking in functional programming -- what would be a local, mutable variable in a loop in an imperative program becomes a parameter to a recursive function in a functional program.
Unfortunately, since wxHaskell is an event-based framework, Don's and ZachS answers don't apply.
What you have to do here is to allocate a mutable variable, just like you would in an imperative language. WxHaskell offers the function variable for that. Here an (incomplete) example:
gui = do
...
counter <- variable [value := 1 :: Int] -- allocate mutable variable
button <- button window [ text := "Count!"
, on command := next counter button]
where
next counter button = do
n <- get counter value -- get its value
set button [text := show n]
set counter [value := n+1] -- set its value
Note that wxHaskell comes with lots of example source code. In particular, wx/ImageViewer.hs features a mutable variable.
However, except for special situations like this, it is beneficial to avoid mutable variables like the plague. (In fact, they make a mess in wxHaskell, too, it's just that they are difficult to avoid here.) Alternatives include rethinking your code, accumulating parameters, using types of the form s -> (a,s) and the state monad.
One way to do this in a functional language is to thread your state through your functions. Some of the functionality will probably be handled by monads, such as getting the keyboard state, so you won't have to handle that yourself. An example (more or less pseudocode):
someFunction :: SomeDataTypeThatRepresentsState -> a ... -> (SDTTRS, a...) (change to fit reality of course)
someFunction x y .... | x == WeHaveKeyboardInput = someFunction dowhatever.....
| someFunction dowhateverelse
That should give you an idea of how to get started.
EDIT:
I should have mentioned Monads more in depth. Monads are basically a way to hide all of that state passing. It's oversimplified, I know, but it gets you started. To read more about monads and handling state, follow this link: http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm
You might also want to check out the simple-observer package on Hackage. (Disclosure: I'm the package maintainer.)
It's a Haskell implementation of the Observer design pattern (just the ticket for solving "make something change every time ..." problems in an event-based framework), using MVars for mutable state. There's a blog post discussing it further here
I created this package when I was faced with exactly the same problem as you.
Related
I don't know how to re-assign a variable in a function.
For example,
elephant = 0
function x = elephant = x
Why doesn't this work?
Haskell is a great imperative language, and writing programs that can re-assign state is a really fun advanced topic! This is definitely not the approach you want right now, but come back to it some day 🙂
It takes a bit of effort to define an environment that models global mutable variables. Once you get the hang of it, though, the precision of the types ends up being pretty handy.
We're going to be using the lens and mtl libraries.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.State
I'll stick with using integers as your question does, but we'll throw in a type alias to remind ourselves that they are being used as the type of the elephant variable.
type Elephant = Integer
You wanted a program whose global mutable state has an elephant. So first let's define what it means to have an elephant. Lens captures this notion nicely.
class HasElephant a
where
elephant :: Lens' a Elephant
Now we can define function, which assigns a new value to elephant.
function :: (MonadState s m, HasElephant s) => Elephant -> m ()
function x =
elephant .= x
The constraints MonadState s m and HasElephant s are saying our program must be able to hold mutable state of some type s, and the type s must have an elephant.
Let's also define a program that prints the elephant.
printElephant :: (MonadState s m, HasElephant s, MonadIO m) => m ()
printElephant =
use elephant >>= (liftIO . print)
This program does I/O (printing), so we have an additional constraint MonadIO m that says our program type m must be able to do I/O.
The elephant variable is probably only one part of some larger program state. Let's define a data type here to represent the entire state (which we'll name Congo just to be cute because the Congo Basin is one place where elephants live).
data Congo = Congo
{ _congoElephant :: Elephant
}
makeLenses ''Congo
(See Control.Lens.TH for a little bit about makeLenses does here using Template Haskell.)
We must define the way in which the Congo has an elephant.
instance HasElephant Congo
where
elephant = congoElephant
Now we can write an example program. Our program will print the value of elephant, then change the value of elephant, then print it again.
main' :: StateT Congo IO ()
main' =
do
printElephant
function 2
printElephant
Then we can run this program.
main :: IO ()
main = Congo 0 & runStateT main' & void
The output is:
0
2
im trying to re-assign an existing variable
You can't do that in Haskell. You can do something close by using IORefs, but this is very rarely the proper solution to a problem - certainly not in situations a beginner might encounter.
Instead you should re-design your program logic, so that it does not require mutable variables to function.
Haskell is a leader in the functional programming world and functional programming is often called "programming without assignment." It's almost the entire point of functional programming to not use assignment. As soon as you've used it, you're not really doing it in a "functional" way any more. Of course there are times for it, but FP tries to minimize those times.
So, to answer your question, "Why doesn't this work?" First of all the syntax is not correct. = does not mean assignment in Haskell. It binds a name to an expression. You cannot do that twice (in the same scope). In other words, "variables" are immutable (like in math). Second, mutation is a side-effecting action and Haskell treats those as impure actions which must be done in the IO world.
I could show you how to actually mutate a reference in Haskell, but I don't think that's what you need at this point.
The most primitive way to bind a variable x to a value v is to write a function taking x as argument, and pass v to that function.
This can sometimes be used to "simulate" the effect of a mutable variable.
E.g., the imperative code
// sum 0..100
i = s = 0;
while (i <= 100) {
s = s+i;
i++;
}
return s;
becomes
final_s = f 0 0 -- the initial values
where
f i s | i <=100 = f (i+1) (s+i) // increment i, augment s
| otherwise = s // return s at the end
The above code is not pretty FP code, but at least it is close enough to imperative code to make it possible to spot the connections.
A final digression:
When one first notices this, it is usually lured to fall into the Blub paradox. One could easily think: "What!? Haskell needs all that stuff to simulate a simple assignment? If in language Blub assignment is trivial, and simulating that in Haskell requires so much effort, then clearly Blub is much better than Haskell!". And this would be a perfect case of the Blub paradox: when a Blub programmer moves to another language, they immediately perceive what can not be directly translated from Blub, and do not notice all the other features of the new language which were not present in Blub.
Their mind now thinks in "Blub", and it requires a great effort to adapt to new models.
Almost as paradoxically, learning both FP and imperative programming is useful precisely because it's non trivial to learn the other paradigm when used to only one of those. If the step between them were narrow, it would not be worth the effort to learn two close approaches to the same problem.
In general this doesn't work because you usually make immutable declarations, rather than specifying a sequence of operations. You can do:
elephant = 3
main = print elephant
But you can also do:
main = print elephant
elephant = 3
Because the code doesn't specify an order of execution, there is no way to interpret multiple assignments as anything other than an error.
If you want to specify a sequence of operations, use do notation:
main = do
let elephant = 0
print elephant
let elephant = 1
print elephant
let elephant = 2
print elephant
The code in a do block is executed in order, so you can effectively reassign variables the way you can in most programming languages.
Note that this code really just creates a new binding for elephant. The old value still exists:
main = do
let elephant = 1
print elephant
let printElephant = print elephant
let elephant = 2
print elephant
printElephant
Because the printElephant function I define is still using the old value of elephant, this prints:
1
2
1
I am writing a simple text editor, so I want to have something like this
type Scancode = Int
data KeyState = Pressed | Released
newtype InStream = InStream [(Scancode, State)]
main = do
input <- getKeys
parse input
parse :: InStream -> IO ()
parse [] = return ()
parse (x : xs)
| x == (1, Released) = return ()
| otherwise = do
doSomething
parse xs
As you could guess, I want getKeys function to behave like getContents, to have continuos list of scancodes.
As I know SDL or even GTK can provide me such functionality, but is there more idiomatic (for haskell and functional programming at all) and with less "overhead" way to do such thing?
P.S. If it matters, I want to use my "editor" under Linux both in console (tty) and X11/Wayland.
If you really want simple, then check out these answers:
What is a simple way to wait for and then detect keypresses in Haskell?
Block until keypress or given time of day
You might have to put your tty into raw mode first for it to work. The second question asks for a Windows solution, but the same idea should also work for Linux.
I have an assignment which is to create a calculator program in Haskell. For example, users will be able to use the calculator by command lines like:
>var cola =5; //define a random variable
>cola*2+1;
(print 11)
>var pepsi = 10
>coca > pepsi;
(print false)
>def coke(x,y) = x+y; //define a random function
>coke(cola,pepsi);
(print 15)
//and actually it's more complicated than above
I have no clue how to program this in Haskell. All I can think of right now is to read the command line as a String, parse it into an array of tokens. Maybe go through the array, detect keywords such "var", "def" then call functions var, def which store variables/functions in a List or something like that. But then how do I store data so that I can use them later in my computation?
Also am I on the right track because I am actually very confused what to do next? :(
*In addition, I am not allowed to use Parsec!*
It looks like you have two distinct kinds of input: declarations (creating new variables and functions) and expressions (calculating things).
You should first define some data structures so you can work out what sort of things you are going to be dealing with. Something like:
data Command = Define Definition | Calculate Expression | Quit
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
-- ^ alternatively, implement variables as zero-argument functions
-- and merge these cases
data Expression = Var Name | Add Expression Expression | -- ... other stuff
type Environment = [Definition]
To start off with, just parse (tokenise and then parse the tokens, perhaps) the stuff into a Command, and then decide what to do with it.
Expressions are comparatively easy. You assume you already have all the definitions you need (an Environment) and then just look up any variables or do additions or whatever.
Definitions are a bit trickier. Once you've decided what new definition to make, you need to add it to the environment. How exactly you do this depends on how exactly you iterate through the lines, but you'll need to pass the new environment back from the interpreter to the thing which fetches the next line and runs the interpreter on it. Something like:
main :: IO ()
main = mainLoop emptyEnv
where
emptyEnv = []
mainLoop :: Environment -> IO ()
mainLoop env = do
str <- getLine
case parseCommnad str of
Nothing -> do
putStrLn "parse failed!"
mainLoop env
Just Quit -> do
return ()
Just (Define d) -> do
mainLoop (d : env)
Just (Calculate e) -> do
putStrLn (calc env e)
mainLoop env
-- the real meat:
parseCommand :: String -> Maybe Command
calc :: Environment -> Expression -> String -- or Integer or some other appropriate type
calc will need to look stuff up in the environment you create as you go along, so you'll probably also need a function for finding which Definition corresponds to a given Name (or complaining that there isn't one).
Some other decisions you should make:
What do I do when someone tries to redefine a variable?
What if I used one of those variables in the definition of a function? Do I evaluate a function definition when it is created or when it is used?
These questions may affect the design of the above program, but I'll leave it up to you to work out how.
First, you can learn a lot from this tutorial for haskell programming
You need to write your function in another doc with .hs
And you can load the file from you compiler and use all the function you create
For example
plus :: Int -> Int -- that mean the function just work with a number of type int and return Int
plus x y = x + y -- they receive x and y and do the operation
I'm using dynamicLogWithPP from XMonad.Hooks.DynamicLog together with dzen2 as a status bar under xmonad. One of the things I'd like to have displayed in the bar is the time remaining in the currently playing track in audacious (if any). Getting this information is easy:
audStatus :: Player -> X (Maybe String)
audStatus p = do
info <- liftIO $ tryS $ withPlayer p $ do
ispaused <- paused
md <- getMetadataString
timeleftmillis <- (-) <$> (getCurrentTrack >>= songFrames) <*> time
let artist = md ! "artist"
title = md ! "title"
timeleft = timeleftmillis `quot` 1000
(minutes, seconds) = timeleft `quotRem` 60
disp = artist ++ " - " ++ title ++ " (-"++(show minutes)++":"++(show seconds)++")" -- will be wrong if seconds < 10
audcolor False = dzenColor base0 base03
audcolor True = dzenColor base1 base02
return $ wrap "^ca(1, pms p)" "^ca()" (audcolor ispaused disp)
return $ either (const Nothing) Just info
So I can stick that in ppExtras and it works fine—except it only gets run when the logHook gets run, and that happens only when a suitable event comes down the pike. So the display is potentially static for a long time, until I (e.g.) switch workspaces.
It seems like some people just run two dzen bars, with one getting output piped in from a shell script. Is that the only way to have regular updates? Or can this be done from within xmonad (without getting too crazy/hacky)?
ETA: I tried this, which seems as if it should work better than it does:
create a TChan for updates from XMonad, and another for updates from a function polling Audacious;
set the ppOutput field in the PP structure from DynamicLog to write to the first TChan;
fork the audacious-polling function and have it write to the second TChan;
fork a function to read from both TChans (checking that they aren't empty, first), and combining the output.
Updates from XMonad are read from the channel and processed in a timely fashion, but updates from Audacious are hardly registered at all—every five or so seconds at best. It seems as if some approach along these lines ought to work, though.
I know this is an old question, but I came here looking for an answer to this a few days ago, and I thought I'd share the way I solved it. You actually can do it entirely from xmonad. It's a tiny bit hacky, but I think it's much nicer than any of the alternatives I've come across.
Basically, I used the XMonad.Util.Timer library, which will send an X event after a specified time period (in this case, one second). Then I just wrote an event hook for it, which starts the timer again, and then manually runs the log hook.
I also had to use the XMonad.Util.ExtensibleState library, because Timer uses an id variable to make sure it's responding to the right event, so I have to store that variable between events.
Here's my code:
{-# LANGUAGE DeriveDataTypeable #-}
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Timer
...
-- wrapper for the Timer id, so it can be stored as custom mutable state
data TidState = TID TimerId deriving Typeable
instance ExtensionClass TidState where
initialValue = TID 0
...
-- put this in your startupHook
-- start the initial timer, store its id
clockStartupHook = startTimer 1 >>= XS.put . TID
-- put this in your handleEventHook
clockEventHook e = do -- e is the event we've hooked
(TID t) <- XS.get -- get the recent Timer id
handleTimer t e $ do -- run the following if e matches the id
startTimer 1 >>= XS.put . TID -- restart the timer, store the new id
ask >>= logHook.config -- get the loghook and run it
return Nothing -- return required type
return $ All True -- return required type
Pretty straightforward. I hope this is helpful to someone.
It cannot be done from within xmonad; xmonad's current threading model is a bit lacking (and so is dzen's). However, you can start a separate process that periodically polls your music player and then use one of the dzen multiplexers (e.g. dmplex) to combine the output from the two processes.
You may also want to look into xmobar and taffybar, which both have better threading stories than dzen does.
With regards to why your proposed TChan solution doesn't work properly, you might want to read the sections "Conventions", "Foreign Imports", and "The Non-Threaded Runtime" at my crash course on the FFI and gtk, keeping in mind that xmonad currently uses GHC's non-threaded runtime. The short answer is that xmonad's main loop makes an FFI call to Xlib that waits for an X event; this call blocks all other Haskell threads from running until it returns.
I'm looking to call functions dynamically based on the contents found in an association list.
Here is an example in semi-pseudo-code. listOfFunctions would be passed to callFunctions.
listOfFunctions = [('function one', 'value one')
, ('function two', 'value two')
, ('function three', 'value three')]
callFunctions x = loop through functions
if entry found
then call function with value
else do nothing
The crux of the question is not looping through the list, rather, it's how to call a function once I have it's name?
Consider this use case for further clarification. You open the command prompt and are presented with the following menu.
1: Write new vHost file
2: Exit
You write the new vHost file and are not presented with a new menu
1: Enter new directive
2: Write file
3: Exit
You enter some new directives for the vHost and are now ready to write the file.
The program isn't going to blindly write each and every directive it can, rather, it will only write the ones that you supplied. This is where the association list comes in. Writing a giant if/then/else or case statement is madness. It would be much more elegant to loop through the list, look for which directives were added and call the functions to write them accordingly.
Hence, loop, find a function name, call said function with supplied value.
Thanks to anyone who can help out with this.
Edit:
Here is the solution that I've come up with (constructive critiques are always welcome).
I exported the functions which write the directives in an association list as every answer provided said that just including the function is the way to go.
funcMap = [("writeServerName", writeServerName)
,("writeServeralias", writeServerAlias)
,("writeDocRoot", writeDocRoot)
,("writeLogLevel", writeErrorLog)
,("writeErrorPipe", writeErrorPipe)
,("writeVhostOpen", writeVhostOpen)]
In the file which actually writes the hosts, that file is imported.
I have an association list called hostInfo to simulate some dummy value that would be gathered from an end-user and a function called runFunction which uses the technique supplied by edalorzo to filter through both the lists. By matching on the keys of both lists I ensure that the right function is called with the right value.
import Vhost.Directive
hostInfo = [("writeVhostOpen", "localhost:80")
,("writeServerName", "norics.com")]
runFunctions = [f val | (mapKey, f) <- funcMap, (key, val) <- hostInfo, mapKey == key]
You can simply include the function in the list directly; functions are values, so you can reference them by name in a list. Once you've got them out of the list, applying them is just as simple as func value. There's no need to involve their names at all.
Since I am farily new to Haskell I will risk that you consider my suggestion very naive, but anyways here it goes:
let funcs = [("sum", (+3),1),("product", (*3),2),("square", (^2),4)]
[f x | (name, f, x) <- funcs, name == "sum"]
I think it satisfies the requirements of the question, but perhaps what you intend is more sofisticated than what I can see with my yet limitted knowledge of Haskell.
It might be a bit of an overkill (I agree with ehird's reasoning) but you can evaluate a string with Haskell code by using the eval function in System.Eval.Haskell.
EDIT
As pointed out in the comments, hint is a better option for evaluating strings with Haskell expressions. Quoting the page:
This library defines an Interpreter monad. It allows to load Haskell modules, browse them, type-check and evaluate strings with Haskell expressions and even coerce them into values. The library is thread-safe and type-safe (even the coercion of expressions to values). It is, esentially, a huge subset of the GHC API wrapped in a simpler API. Works with GHC 6.10.x and 6.8.x
First we define our list of functions. This could be built using more machinery, but for the sake of example I just make one explicit list:
listOfFunctions :: [(Int, IO ())]
listOfFunctions = [(0, print "HI") -- notice the anonymous function
,(1, someNamedFunction) -- and something more traditional here
]
someNamedFunction = getChar >>= \x -> print x >> print x
Then we can select from this list however we want and execute the function:
executeFunctionWithVal :: Int -> IO ()
executeFunctionWithVal v = fromMaybe (return ()) (lookup v listOfFunctions)
and it works (if you import Data.Maybe):
Ok, modules loaded: Main.
> executeFunctionWithVal 0
"HI"
> executeFunctionWithVal 01
a'a'
'a'
Don't store the functions as strings, or rather, try storing the actual functions and then tagging them with a string. That way you can just call the function directly. Functions are first class values, so you can call the function using whatever name you assign it to.