fho
fho

Reputation: 6798

How does `lens` work?

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?

Upvotes: 1

Views: 435

Answers (1)

Chris Kuklewicz
Chris Kuklewicz

Reputation: 8153

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.

Upvotes: 1

Related Questions