Haskell UI do clause, how to print?
Asked Answered
S

1

3

This is a follow up question to this. I'm using a graphic library in Haskell called Threepenny-GUI. In this library the main function returns a UI monad object. I'm trying to execute a simple print command with no success. What is a right work around to enable printing for debugging purposes.

Code:

main :: IO ()
main = startGUI defaultConfig setup

setup :: Window -> UI ()
setup w = do

print "debug message 1 "

Error:

Couldn't match type ‘IO’ with ‘UI’
Expected type: UI ()
  Actual type: IO ()
In a stmt of a 'do' block: print "labels and values "
Silique answered 22/6, 2015 at 19:50 Comment(3)
Your do block must contain only one monad (ie either UI or IO but not both). If you want to debug in Haskell, a debugger might be useful.Goings
How do I support print then?Silique
You should try to preserve the formatting of your Haskell code in your code blocks. The code in your question has a parse error because there are no spaces before print. One thing that helps is StackOverflow shortcut Ctrl-k. If you highlight a block of text in a question or answer and hit Ctrl-k, it will indent each line by 4 spaces. As far as I know, this shortcut isn't officially documented anywhere but it's handy.Xerox
X
5

Based on the types, this is a good application of liftIO. liftIO has a type MonadIO m => IO a -> m a so it can be used like this:

liftIO (print "debug message 1")

The type of that expression can be UI () since UI is an instance of MonadIO and print "debug message 1" has the type IO ().

Xerox answered 22/6, 2015 at 19:58 Comment(4)
The only reason to apply liftio then is to wrap the unused result of print so it won't shout at me?Silique
@Silique No. The unused output is (). The type of the IO action is IO (). In Haskell, IO actions are first-class values, so the value print "debug message 1" is the IO action that prints that message, not ().Xerox
To give another example, if you want to read in a String from stdin inside of UI, you could write: do ... ; someInput <- liftIO getLine ; ...(note that the type of getLine is IO String). liftIO lifts IO actions.Xerox
By the way: if you wanted to print to the console in response to a button click or some other UI event, rather than during the GUI initialisation, you would use either onEvent or on. In that case, the liftIO would appear in the (a -> UI void) callback passed to onEvent/on.Steersman

© 2022 - 2024 — McMap. All rights reserved.