
I'm having a lot of trouble mixing file io and wxhaskell's varCreate/Get/Set functions. I have functions readWords :: String -> IO WordMap wordGrid :: WordMap -> Layout And within my GUI code, the following compiles (ignores the variable, basically): words <- varCreate (do {w <- readWords "words"; return w}) wGrid <- do w <- readWords "words" return $ wordGrid w but I can't get the following (noncompiling code, but it shows what I'm trying to do) working: wGrid <- do w <- varGet words return $ wordGrid w Could someone give me a minimal example of reading in a list of words from a file, binding a wxHaskell variable to the list, and then mapping some GUI code over it? (Also, I'm making the base assumption that varSet and varGet are wxHaskell's analogue of the State monad - should I be looking at using StateT instead?) martin

martindemello:
I'm having a lot of trouble mixing file io and wxhaskell's varCreate/Get/Set functions. I have functions
readWords :: String -> IO WordMap wordGrid :: WordMap -> Layout
And within my GUI code, the following compiles (ignores the variable, basically):
words <- varCreate (do {w <- readWords "words"; return w}) wGrid <- do w <- readWords "words" return $ wordGrid w
but I can't get the following (noncompiling code, but it shows what I'm trying to do) working:
wGrid <- do w <- varGet words return $ wordGrid w
Could someone give me a minimal example of reading in a list of words from a file, binding a wxHaskell variable to the list, and then mapping some GUI code over it?
Here's an efficient read-words-from-file function: $ cat A.hs import qualified Data.ByteString.Char8 as S (words,readFile) import Data.ByteString (ByteString) getWords :: FilePath -> IO [ByteString] getWords f = fmap S.words (S.readFile f) main = print . length =<< getWords "/usr/share/dict/words" $ time ./A 234979 ./A 0.09s user 0.01s system 94% cpu 0.107 total If you wanted to turn this list of words into a Map, something like: buildMap :: [ByteString] -> M.Map ByteString Int buildMap xs = M.fromListWith (+) (zip xs (repeat 1)) (untested). As for wxHaskell, I'll have to defer to the ui hackers for that. -- Don

Martin DeMello said:
I'm having a lot of trouble mixing file io and wxhaskell's varCreate/Get/Set functions. I have functions
readWords :: String -> IO WordMap wordGrid :: WordMap -> Layout
And within my GUI code, the following compiles (ignores the variable, basically):
words <- varCreate (do {w <- readWords "words"; return w})
I'm not familiar with wxHaskell, but I don't think wxHaskell is your problem here. It looks like you are confusing yourself with overuse of "do" notation, and perhaps a lack of understanding of the monad laws. Whenever you see this: v <- expr return v You can replace it with just "expr". Your code above reduces to: words <- varCreate (readWords "words") So the variable you are creating has type (IO WordMap), when you probably wanted it to have type WordMap. By itself, this compiles, because IO actions are values as good as any other. The problem only manifests when you combine it with code that tries to read the variable as if it had type WordMap. This is probably what you wanted (untested): w <- readWords "words" words <- varCreate w Now, the variable has type WordMap.
wGrid <- do w <- readWords "words" return $ wordGrid w
but I can't get the following (noncompiling code, but it shows what I'm trying to do) working:
wGrid <- do w <- varGet words return $ wordGrid w
With the above change, this should now work, though it might be clearer to write this as: wGrid <- liftM wordGrid $ varGet words
Could someone give me a minimal example of reading in a list of words from a file, binding a wxHaskell variable to the list, and then mapping some GUI code over it?
(Also, I'm making the base assumption that varSet and varGet are wxHaskell's analogue of the State monad - should I be looking at using StateT instead?)
The wxHaskell Var type is not quite like the State monad. It is a type of mutable variable in the IO monad, much like the IORef type. Try to avoid gratuitous use of mutable variables, as they can weaken your ability to reason about your code. I'm not convinced you really need one here. What problem are you trying to solve by using a mutable variable?

On 2/5/07, Matthew Brecknell
I'm not familiar with wxHaskell, but I don't think wxHaskell is your problem here. It looks like you are confusing yourself with overuse of "do" notation, and perhaps a lack of understanding of the monad laws. Whenever you see this:
v <- expr return v
You can replace it with just "expr". Your code above reduces to:
words <- varCreate (readWords "words")
Okay - was confused about that. Thanks for the tip.
So the variable you are creating has type (IO WordMap), when you probably wanted it to have type WordMap. By itself, this compiles, because IO actions are values as good as any other. The problem only manifests when you combine it with code that tries to read the variable as if it had type WordMap.
This is probably what you wanted (untested):
w <- readWords "words" words <- varCreate w
That didn't work, because (as someone on #haskell explained to me) readWords has type IO and the wx actions have type Layout
The wxHaskell Var type is not quite like the State monad. It is a type of mutable variable in the IO monad, much like the IORef type. Try to avoid gratuitous use of mutable variables, as they can weaken your ability to reason about your code. I'm not convinced you really need one here. What problem are you trying to solve by using a mutable variable?
You're right, I don't need mutable variables, just some sort of state. I'm writing a game which presents the user with a list of anagrams (read in from a file) and an input box in which to enter guesses. The input box's on command is (pseudocode) a <- get input text if exists a wordmap remove a wordmap update display else say "wrong" So what I need is for the gui code to have a single wordmap threaded through it. I thought I could do that by reading in the wordmap within the gui do sequence and binding it to a variable. martin

On 2/5/07, Martin DeMello
On 2/5/07, Matthew Brecknell
wrote: This is probably what you wanted (untested):
w <- readWords "words" words <- varCreate w
That didn't work, because (as someone on #haskell explained to me) readWords has type IO and the wx actions have type Layout
Okay, I was probably doing something else wrong, because I just tried this again (after changing some other code) and it worked perfectly. martin
participants (3)
-
dons@cse.unsw.edu.au
-
Martin DeMello
-
Matthew Brecknell