1

I mean, not the simple stuff like this (from here):

strike :: StateT Game IO ()
strike = do
    lift $ putStrLn "*shink*"
    boss.health -= 10

But things like using lens to map over types from Linear. How would I express this in terms of lens:

vecMod :: (Integral a) => V2 a -> V2 a -> V2 a
vecMod (V2 x1 y1) (V2 x2 y2) = V2 (x1 `mod` x2) (y1 `mod` y2)

Another example: my current code is full of small expressions like this:

isAt :: Thing -> Position -> Game Bool
isAt thing pos = do
  b <- use board
  return $ elem thing (b ! pos)

(where board is Array (V2 Int))

I guess is that there (with lens) there is a more canonical way to express this.

In general: how do I find out what lens is able to do, what not and how it is done?

fho
  • 6,787
  • 26
  • 71

1 Answers1

1

The first vecMod is easy to simplify:

import Control.Applicative

data V2 a = V2 a a  deriving Show

instance Functor V2 where
    fmap f (V2 x y) = V2 (f x) (f y)

instance Applicative V2 where
    pure x = V2 x x
    (V2 f g) <*> (V2 x y) = V2 (f x) (g y)

vecMod1,vecMod2 :: (Integral a) => V2 a -> V2 a -> V2 a
vecMod1 (V2 x1 y1) (V2 x2 y2) = V2 (x1 `mod` x2) (y1 `mod` y2)
vecMod2 = liftA2 mod

You can see liftA2 works because I made V2 applicative in the obvious way.

The second is already quite terse. If you post a collections of such snippets we could help abstract a few things.

Chris Kuklewicz
  • 8,123
  • 22
  • 33
  • Hmm ok ... this is easier right. But still the question on how to find useful information in the `lens` library stands. – fho Sep 22 '13 at 18:58
  • The Functor/Applicative instances for V2 are already defined in the linear package – bennofs Sep 22 '13 at 19:06
  • @bennofs yep ... i noticed that. Actually I was thinking about tuples where no such method exists. – fho Sep 22 '13 at 19:58