I have a small working SDL2 sample (a straightforward port of a C++ tutorial) and am trying to refactor the rendering code into using the (->) r monad. Here's the working part of the sample without the refactoring
renderClear renderer
renderCopy renderer texture nullPtr nullPtr
renderPresent renderer
Make & run - the texture is there. Both
renderClear renderer
flip ($) renderer $ do
copy texture nullPtr nullPtr
renderPresent renderer
and
renderClear renderer
renderCopy renderer texture nullPtr nullPtr
flip ($) renderer $ do
present
work fine too. Yet
renderClear renderer
flip ($) renderer $ do
copy texture nullPtr nullPtr
present
just draws the black window and that's it. present is an alias of renderPresent and copy is renderCopy with first argument shifted to the end. Do it have something to do with these functions working with IO? How can I fix this?
When you combine it into
flip ($) renderer $ do
copy texture nullPtr nullPtr
present
the whole do block is in the (->) r monad, and so the actions are not sequenced by IO or whatever underlying monad you have, instead using essentially
(f >> g) x = g x
leaving only present in the combination.
The way to fix this, I think, is to use a ReaderT monad transformer which knows how to use the underlying monad when sequencing, turning it into something like (you'll need to redefine copy and present appropriately)
flip runReaderT renderer $ do
copy texture nullPtr nullPtr
present
Related
I have a web application written in Haskell (using ghcjs on the client side and ghc on the server side) and I need a way to collect the CSS values which are spread throughout the modules. Currently I use a technique involving a CssStyle class and template haskell. When a module needs to export some CSS it creates a CssStyle instance for some type (the type has no significance except that it must be unique.) In the top level all the CssStyle instances are retrieved using the reifyInstances function from template haskell.
This approach has at least two drawbacks: You have to create meaningless types to attach the instances to, and you have to be sure all the instances are imported in the place where you scan and turn into real CSS. Can anyone think of a more beautiful way to collect data embedded in Haskell code?
================
Quelklef has requested some source code demonstrating the current solution:
{-# LANGUAGE AllowAmbiguousTypes, OverloadedStrings, MultiParamTypeClasses, TemplateHaskell, LambdaCase, FunctionalDependencies, TypeApplications #-}
import Clay
import Control.Lens hiding ((&))
import Data.Proxy
import Language.Haskell.TH
class CssStyle a where cssStyle :: Css
-- | Collect all the in scope instances of CssStyle and turn them into
-- pairs that can be used to build scss files. Result expression type
-- is [(FilePath, Css)].
reifyCss :: Q Exp
reifyCss = do
insts <- reifyInstances ''CssStyle [VarT (mkName "a")]
listE (concatMap (\case InstanceD _ _cxt (AppT _cls typ#(ConT tname)) _decs ->
[ [|($(litE (stringL (show tname))), $(appTypeE [|cssStyle|] (pure typ)))|] ]
_ -> []) insts)
data T1 = T1
instance CssStyle T1 where cssStyle = byClass "c1" & flexDirection row
data T2 = T2
instance CssStyle T2 where cssStyle = byClass "c2" & flexDirection column
-- Need to run this in the interpreter because of template haskell stage restriction:
--
-- > fmap (over _2 (renderWith compact [])) ($reifyCss :: [(String, Css)])
-- [("Main.T2",".c2{flex-direction:column}"),("Main.T1",".c1{flex-direction:row}")]
The point here is that any CssStyle instance from any module imported here will appear in this list, not only those defined locally.
Hmm...
I do not officially recommend your current approach. It's making use of typeclasses in a highly unorthodox way, so it's unlikely to act exactly as you like. As you've already noted, in order for it to work you need to make sure that all CssStyle instances are in scope, which is pretty arcane behaviour. Also, the current approach does not compose well, by which I mean that your css-related computation is all happening in the global context.
Unfortunately, I don't know of any canonical way to do what you want at compile-time.
However, I do have one idea. Most programs run in top-level "industrial" monads, and I'm assuming your program does as well. You could wrap your industrial monad with a new applicative (not monad) F. The role of this applicative is to allow subprograms to propagate their CSS needs to callers. Concretely, there would be a function style :: Css -> F () which acts akin to how tell acts in a writer monad. There would also be affordances to embed actions from your industrial monad into F. Then each module which has its own CSS exports its API wrapped F; doing this tracks the CSS requirements. There would be a function compileCss :: F a -> Css which builds the composite CSS style and does not execute any effectful operations embedded within F. Additionally, there would be a function execute :: F a -> IO a which executes the actions embedded in the F a value. Then main could make use of compileCss to emit the CSS, and make use of execute to separately run the program.
I admit this is somewhat awkward... wrapping all your existing code in F will be annoying at best. However, I do think it is at least correct, insofar as it tracks effects.
Perhaps the proper answer is to use an existing component-based web framework, which allows you define your component markup and styling in the same place? Some of them support emitting to static HTML.
In PL class we were asked to make a pacman clone in Gloss, nevertheless I got stuck at making the map.
My approach was taking a .png of the classical pacman first level, and paste it in the render function so I don't need to draw everything by hand.
Nevertheless by doing so, the games lags horribly, I'm assuming that it's because the game renders the map in every step.
Is there some way to just render the map as a background a single time, or avoid the huge lag? Or am I taking a bad approach and it would it be better if I draw the components by hand using the Picture module?
I append the render function just in case I'm wiring it badly:
render :: PacmanGame -> IO Picture
render game = do
sprite <- fmap (head) (playerSprites $ player game)
let playerOne = uncurry translate (playerPos $ player game) $ sprite
map' <- pacmanMap
return $ pictures [map', playerOne]
Where pacmanMap :: IO Picture
It looks like you’re reloading the file in every call to render. You need to run the pacmanMap :: IO Picture action once, for example at startup in main; then you can just return the resulting static Picture from your render function. For example, you might store the reference to the current background image in the PacmanGame, or pass it as an additional argument to render.
Is there a function, similar to JS screen.width and screen.height in Haskell with the gloss graphic library, which returns the screen width and height?
There is the function is in Graphics.Gloss.Interface.Environment called getScreenSize it return a IO (Int,Int) the first value is width, the second is height.
I don't think gloss itself exports this capability, but you can use these calls from the GLFW package to determine the screen resolution:
import Graphics.UI.GLFW
main = do
initialize
desktopMode >>= print
putStrLn "all video modes:"
videoModes >>= mapM_ print
Note that gloss may be compiled to use either GLUT or GLFW. If gloss uses GLFW as its interface to Open GL it will call GLFW's initialize function when you create a window, and it's possible there is an issue with calling initialize twice in the same process but I kinda doubt it.
You can then use these dimensions to set the drawable area when creating a gloss window with the FullScreen constructor.
The title says it all. I've seen that some people apparently use Data.Conduit.List.map id as identity conduit, but is this the recommended way to stream data unchanged?
The simplest way to write an identity conduit is probably:
awaitForever yield
because this doesn't require an extra import.
The definition of Data.Conduit.List.map is very similar:
mapC f = awaitForever $ yield . f
(The difference between mapC and map has something to do with CPP macros to define fusion.)
When optimization is on (-O1), it appears both options result in identical code, so it's just a matter of taste.
Given a Haskell expression, I'd like to perform alpha conversion, ie. rename some of the non free variables.
I've started implementing my own function for this, which works on a haskell-src-exts Exp tree, however it turns out to be surprisingly nontrivial, so I can't help wondering - is there an established easy-to-use library solution for this kind of source conversion? Ideally, it should integrate with haskell-src-exts.
This is one of the problems where the "Scrap Your Boilerplate" style generic libraries shine!
The one I'm most familiar with is the uniplate package, but I don't actually have it installed at the moment, so I'll use the (very similar) functionality found in the lens package. The idea here is that it uses Data.Data.Data (which is the best qualified name ever) and related classes to perform generic operations in a polymorphic way.
Here's the simplest possible example:
alphaConvert :: Module -> Module
alphaConvert = template %~ changeName
changeName :: Name -> Name
changeName (Ident n) = Ident $ n ++ "_conv"
changeName n = n
The (%~) operator is from lens and just means to to apply the function changeName to everything selected by the generic traversal template. So what this does is find every alphanumeric identifier and append _conv to it. Running this program on its own source produces this:
module AlphaConv where
import Language.Haskell.Exts
import Control.Lens
import Control.Lens.Plated
import Data.Data.Lens
instance Plated_conv Module_conv
main_conv
= do ParseOk_conv md_conv <- parseFile_conv "AlphaConv.hs"
putStrLn_conv $ prettyPrint_conv md_conv
let md'_conv = alphaConvert_conv md_conv
putStrLn_conv $ prettyPrint_conv md'_conv
alphaConvert_conv :: Module_conv -> Module_conv
alphaConvert_conv = template_conv %~ changeName_conv
changeName_conv :: Name_conv -> Name_conv
changeName_conv (Ident_conv n_conv)
= Ident_conv $ n_conv ++ "_conv"
changeName_conv n_conv = n_conv
Not terribly useful since it doesn't distinguish between identifiers bound locally and those defined in an outside scope (such as being imported), but it demonstrates the basic idea.
lens may seem a bit intimidating (it has a lot more functionality than just this); you may find uniplate or another library more approachable.
The way you'd approach your actual problem would be a multi-part transformation that first selects the subexpressions you want to alpha-convert inside of, then uses a transformation on those to modify the names you want changed.