IO (Maybe Picture) -> Picture - haskell

I'm creating a game with Gloss.
I have this function :
block :: IO (Maybe Picture)
block = loadJuicyPNG "block.png"
How do I take this IO (Maybe Picture) and turn it into a Picture?

You need to bind the value. This is done either with the bind function (>>=), or by do-notation:
main :: IO ()
main = do
pic <- block
case pic of
Just p -> ... -- loading succeeded, p is a Picture
Nothing -> ... -- loading failed
It is a Maybe Picture because the loading might fail, and you have to handle that possible failure somehow.

This is basically the same answer as Bartek's, but using a different approach.
Let's say you have a function foo :: Picture -> Picture the transforms a picture in some way. It expects a Picture as an argument, but all you have is block :: IO (Maybe Picture); there may or may not be a picture buried in there, but it's all you have.
To start, let's assume you have some function foo' :: Maybe Picture -> Maybe Picture. It's definition is simple:
foo' :: Maybe Picture -> Maybe Picture
foo' = fmap foo
So simple, in fact, that you never actually write it; wherever you would use foo', you just use fmap foo directly. What this function does, you will recall, is return Nothing if it gets Nothing, and return Just (foo x) if it gets some value Just x.
Now, given that you have foo', how do you apply it to the value buried in the IO type? For that, we'll use the Monad instanced for IO, which provides us with two functions (types here specialized to IO):
return :: a -> IO a
(>>=) :: IO a -> (a -> IO b) -> IO b
In our case, we recognize that both a and b are Maybe Picture. If foo' :: Maybe Picture -> Maybe Picture, then return . foo' :: Maybe Picture -> IO (Maybe Picture). That means we can finally "apply" foo to our picture:
> :t block >>= return . (fmap foo)
block >>= return . (fmap foo) :: IO (Maybe Picture)
But we aren't really applying foo ourselves. What we are really doing is lifting foo into a context where, once block is executed, foo' can be called on whatever block produces.

Related

How can I modify the windowSet in XMonad?

I have a function that looks like:
sinkFocus :: StackSet i l a s sd -> Maybe (StackSet i l a s sd)
sinkFocus = (fmap . flip sink) <*> peek
However I would like an X () so that I can use it. For example additionalKeys uses an X ().
The documentation says that X is a IO with some state and reader transformers, so I am under the impression that the StackSet is contained within the state of X. So in theory it should be possible to modify the relevant part of the state. However the state accessible is XState not the StackState I want, so I need to be able to turn my function on StackState to one on XState.
This would be easy enough if I had a function of the type
(StackSet i l a s sd -> StackSet i l a s sd) -> X ()
However after digging around in the documentation I haven't been able to piece together a way to do this yet. Is there a way to take a function on StackSet and make an X () that performs that function?
The X monad has an instance of MonadState
instance MonadState XState X
So we can use modify as
modify :: (XState -> XState) -> X ()
So we need to turn out function to one on XStates. And if we look at the definition
XState
windowset :: !WindowSet
mapped :: !(Set Window)
waitingUnmap :: !(Map Window Int)
dragging :: !(Maybe (Position -> Position -> X (), X ()))
numberlockMask :: !KeyMask
extensibleState :: !(Map String (Either String StateExtension))
we will see WindowSet which is a type alias for a particular StackState. So you can turn a function from StackStates into one on XStates like so:
overWindowSet :: (WindowSet -> WindowSet) -> XState -> XState
overWindowSet f xState = xState { windowset = f (windowset xState) }
This can be combined with modify to make the complete function you would like:
modify . overWindowSet

How to interact with pure algorithm in IO code

To illustrate the point with a trivial example, say I have implemented filter:
filter :: (a -> Bool) -> [a] -> [a]
And I have a predicate p that interacts with the real world:
p :: a -> IO Bool
How do it make it work with filter without writing a separate implementation:
filterIO :: (a -> IO Bool) -> [a] -> IO [a]
Presumably if I can turn p into p':
p': IO (a -> Bool)
Then I can do
main :: IO ()
main = do
p'' <- p'
print $ filter p'' [1..100]
But I haven't been able to find the conversion.
Edited:
As people have pointed out in the comment, such a conversion doesn't make sense as it would break the encapsulation of the IO Monad.
Now the question is, can I structure my code so that the pure and IO versions don't completely duplicate the core logic?
How do it make it work with filter without writing a separate implementation
That isn't possible and the fact this sort of thing isn't possible is by design - Haskell places firm limits on its types and you have to obey them. You cannot sprinkle IO all over the place willy-nilly.
Now the question is, can I structure my code so that the pure and IO versions don't completely duplicate the core logic?
You'll be interested in filterM. Then, you can get both the functionality of filterIO by using the IO monad and the pure functionality using the Identity monad. Of course, for the pure case, you now have to pay the extra price of wrapping/unwrapping (or coerceing) the Identity wrapper. (Side remark: since Identity is a newtype this is only a code readability cost, not a runtime one.)
ghci> data Color = Red | Green | Blue deriving (Read, Show, Eq)
Here is a monadic example (note that the lines containing only Red, Blue, and Blue are user-entered at the prompt):
ghci> filterM (\x -> do y<-readLn; pure (x==y)) [Red,Green,Blue]
Red
Blue
Blue
[Red,Blue] :: IO [Color]
Here is a pure example:
ghci> filterM (\x -> Identity (x /= Green)) [Red,Green,Blue]
Identity [Red,Blue] :: Identity [Color]
As already said, you can use filterM for this specific task. However, it is usually better to keep with Haskell's characteristic strict seperation of IO and calculations. In your case, you can just tick off all necessary IO in one go and then do the interesting filtering in nice, reliable, easily testable pure code (i.e. here, simply with the normal filter):
type A = Int
type Annotated = (A, Bool)
p' :: Annotated -> Bool
p' = snd
main :: IO ()
main = do
candidates <- forM [1..100] $ \n -> do
permitted <- p n
return (n, permitted)
print $ fst <$> filter p' candidates
Here, we first annotate each number with a flag indicating what the environment says. This flag can then simply be read out in the actual filtering step, without requiring any further IO.
In short, this would be written:
main :: IO ()
main = do
candidates <- forM [1..100] $ \n -> (n,) <$> p n
print $ fst <$> filter snd candidates
While it is not feasible for this specific task, I'd also add that you can in principle achieve the IO seperation with something like your p'. This requires that the type A is “small enough” that you can evaluate the predicate with all values that are possible at all. For instance,
import qualified Data.Map as Map
type A = Char
p' :: IO (A -> Bool)
p' = (Map.!) . Map.fromList <$> mapM (\c -> (c,) <$> p c) ['\0'..]
This evaluates the predicate once for all of the 1114112 chars there are and stores the results in a lookup table.

Lifted „if“-function behaves unexpectedly

in my program I use a function if' defined in one of the modules instead of the built-in if-then-else construct. It is defined trivially and works just fine.
However, there's one place in code where I need to apply it to monad values (IO in my case), i.e. the type signature should look somewhat like IO Bool -> IO a -> IO a -> IO a.
Naturally, I tried to lift it.
if' <$> mb <*> action1 <*> action2
But when I try to evaluate the expression, I don't get what I expect.
*Main> if' <$> return True <*> putStrLn "yes" <*> putStrLn "no"
yes
no
I know that <*> description reads „sequential application“, so maybe it's that. But what is happening here? Can I fix it without writing a whole new dedicated function?
(<*>) evaluates both of its arguments, so it effectively a pipeline of applications lifted over some applicative. The ability to inspect values and change the future of the computation is the extra power that the Monad class has over Applicative so you need to use that instead e.g.
mif' :: Monad m => m Bool -> m a -> m a -> m a
mif' bm xm ym = bm >>= (\b -> if b then xm else ym)

Caching internals with a partially applied function

Imagine such a function:
bar :: Foo -> A -> B -> C -> IO ()
That function performs some IO stuff using a Foo and other values. The Foo value has to be passed to bar, and can be retrieved from IO via this:
foo :: X -> IO Foo
Now, A, B, C and X are all plain pure values. I’d rather like such a bar function:
bar :: X -> A -> B -> C -> IO ()
And Foo would be generated in the bar function using the X value. If I do that :
let f = bar myX
f :: A -> B -> C -> IO (). If I call that function several times, the X value remains the same because of partial application, but since it’s an IO effect, it will be generated each time. Is there a native, built-in-ghc way to perform some kind of caching so that the Foo value is generated once – for the generated closure? I guess it’s all boxing-related, but I never figured out how to do that without using dirty IORef, expanding the parameters of bar, which is ugly.
What you are literally asking would break referential transparency, a big "no" in Haskell. So that leaves me with the question, should I show you the unsafeLaunchMissiles kind of method that does (sometimes, if you are lucky and optimizations don't break it) what you literally ask but is highly discouraged, or should I show the clean way that changes the types just a little? Let me try the latter.
If you make your bar have the following type instead:
bar :: X -> IO (A -> B -> C -> IO ())
Then you can use, in a do block:
f <- bar myX
Alternatively, if you think that misses the point of redefining bar to take an X, then instead keep your first type for bar and do
f <- bar =<< foo myX

Haskell confusion with ContT, callCC, when

Continuing quest to make sense of ContT and friends. Please consider the (absurd but illustrative) code below:
v :: IO (Either String [String])
v = return $ Left "Error message"
doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
x <- liftIO $ v
x2 <- either (k . Left) return x
when True $ k (Left "Error message 2")
-- k (Left "Error message 3")
return $ Right () -- success
This code does not compile. However, if the replace the when with the commented k call below it, it compiles. What's going on?
Alternatively, if I comment out the x2 line, it also compiles. ???
Obviously, this is a distilled version of the original code and so all of the elements serve a purpose. Appreciate explanatory help on what's going on and how to fix it. Thanks.
The problem here has to do with the types of when and either, not anything particular to ContT:
when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
The second argument needs to be of type m () for some monad m. The when line of your code could thus be amended like so:
when True $ k (Left "Error message 2") >> return ()
to make the code compile. This is probably not what you want to do, but it gives us a hint as to what might be wrong: k's type has been inferred to be something unpalatable to when.
Now for the either signature: notice that the two arguments to either must be functions which produce results of the same type. The type of return here is determined by the type of x, which is in turn fixed by the explicit signature on v. Thus the (k . Left) bit must have the same type; this in turn fixes the type of k at (GHC-determined)
k :: Either String () -> ContT (Either String ()) IO [String]
This is incompatible with when's expectations.
When you comment out the x2 line, however, its effect on the type checker's view of the code is removed, so k is no longer forced into an inconvenient type and is free to assume the type
k :: Either [Char] () -> ContT (Either [Char] ()) IO ()
which is fine in when's book. Thus, the code compiles.
As a final note, I used GHCi's breakpoints facility to obtain the exact types of k under the two scenarios -- I'm nowhere near expert enough to write them out by hand and be in any way assured of their correctness. :-) Use :break ModuleName line-number column-number to try it out.

Resources