Skip to content

Instantly share code, notes, and snippets.

@cdepillabout
Created August 4, 2017 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdepillabout/f8568dd4798703eb7bd7a063268c8ed3 to your computer and use it in GitHub Desktop.
Save cdepillabout/f8568dd4798703eb7bd7a063268c8ed3 to your computer and use it in GitHub Desktop.
Example of creating lenses in Haskell from scratch.
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE RankNTypes #-}
module Main where
import Data.Functor.Identity (Identity(Identity, runIdentity))
type Lens s a = forall f. Functor f => (a -> f a) -> s -> f s
data UserName = UserName { first :: String, second :: String } deriving Show
data User = User { userName :: UserName, userAge :: Int } deriving Show
exampleUserName :: UserName
exampleUserName = UserName "Peter" "Jackson"
exampleUser :: User
exampleUser = User exampleUserName 50
data Const a z = Const { unConst :: a } deriving Functor
-- set :: (forall f. Functor f => (a -> f a) -> s -> f s) -> a -> s -> s
set :: ((a -> Identity a) -> s -> Identity s) -> a -> s -> s
set lll newA s = runIdentity $ lll (\_ -> Identity newA) s
-- view :: (forall f. Functor f => (a -> f a) -> s -> f s) -> s -> a
view :: ((a -> Const a a) -> s -> Const a s) -> s -> a
view lll s = unConst $ lll Const s
userNameLens :: Lens User UserName
userNameLens a2fa user@(User name age) =
fmap (\newName -> User newName age) (a2fa name)
firstNameLens :: Lens UserName String
firstNameLens a2fa (UserName first' second') =
fmap (\newFirst -> UserName newFirst second') $ a2fa first'
userToFirstLens :: Lens User String
userToFirstLens = userNameLens . firstNameLens
example1 :: String
example1 = view userToFirstLens exampleUser
example2 :: User
example2 = set userToFirstLens "new first name" exampleUser
main :: IO ()
main = pure ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment