Created
July 14, 2021 07:22
-
-
Save etorreborre/3f4eff01ed3cb0ef66cabe5e3d3a2e39 to your computer and use it in GitHub Desktop.
Optics with the Witch library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE TemplateHaskell #-} | |
import qualified Data.Text as T | |
import Optics as O | |
import Protolude hiding ((%), from) | |
import Witch | |
import Data.Coerce | |
-- 2 different temperature types | |
newtype Kelvin = Kelvin Double deriving (Eq, Show, Num) | |
newtype Celsius = Celsius Double deriving (Eq, Show, Num) | |
-- conversions between the 2 different temperature types | |
instance From Kelvin Celsius where | |
from (Kelvin k) = Celsius (k - 273.15) | |
instance From Celsius Kelvin where | |
from (Celsius c) = Kelvin (c + 273.15) | |
-- measured temperature is stored as Kelvin | |
data Temperature = Temperature | |
{ _location :: Text, | |
_measured :: Kelvin | |
} | |
deriving (Eq, Show) | |
makeLenses ''Temperature | |
-- we can use from to implement a celsius lens | |
celsius :: Lens' Temperature Celsius | |
celsius = lens getter setter | |
where | |
getter = from . view measured | |
setter temp c = set measured (from c) temp | |
-- we can also redefine set and view to use a From instance | |
set' :: (Is k A_Setter, From c b) => Optic k is s t a b -> c -> s -> t | |
set' o b s = set o (from b) s | |
view' :: (Is k A_Getter, From a b) => Optic' k is s a -> s -> b | |
view' o s = from $ view o s | |
-- example: we modify a measured temperature directly even if the | |
-- measurement is in Celsius | |
> let t = Temperature "here" (Kelvin 300) | |
> set' measured (Celsius 20) t | |
Temperature {_location = "here", _measured = Kelvin 293.15} | |
it :: Temperature | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment