Unknown syntax to modify Haskell Record
data Person = Person {
name :: String,
age :: Int
} deriving (Show, Eq)
modifyAge :: (Int -> Int) -> Person -> Person
modifyAge f p@(Person _ a) = p {age = f a}
let p = Person {name = "Rebecca", age = 18}
let p1 = modifyAge (+1) p
print p1
// Set age
let p2 = modifyAge (const 30) p
print p2
Modify Haskell Record 2
modifyPerson :: (Int -> Int) -> Person -> Person
modifyPerson f p = (\x -> p {age = x}) $ f $ age p
↑
+ -> Person {age = x, name = name p}
p /= p
↑
+ -> Two p are different
Haskell Type Constructor is just a function
data MyType = R Int String | S Int Int deriving (Show)
:t R
R::Int → String → MyType
:t S
S::Int → Int → MyType
Haskell Record is just a function too
data Rec a = Rec{runRec :: String → [(a, String)]}
:t runRec
runRec :: Rec a → String → [(a, String)]
-- We can define a "same" function like runRec
getRec :: Rec a → String → [(a, String)]
getRec (Rec f) = f
-- It is the same
getRec :: Rec a → String → [(a, String)]
getRec (Rec f) s = f s
Understand runState in State monad
Once we understand Rec a, runState is the same as getRec or runRec
newtype StateX s a = StateX{runStateX :: s → (a, s)}
:t runStateX
-- runStatex becomes the following function
runStateX :: StateX s a → s → (a, s)
-- write your own function for runStateX
+ → Type Constructor
↓
getStateX :: (StateX s a) → s → (a, s)
getStateX (StateX f) s = f s
↑ ↑
| + ⟹ f :: s → (a, s)
|
+ → Value Constructor
getStateX (StateX f) = f
↑
|
+ → Unwrap/UnBoxed StateX to access f
-- GHC generate runStateX like getStateX ?
let ss = StateX (\s → ("abc", s)) -- Use the Value Constructor to create a type StateX s String
:i ss
ss :: (String a) ⟹ StateX s a
-- Or we can pass a function to StateX
let g = \s → ("abc", s)
let st = StateX g
:i st
st :: (String a) ⟹ StateX s a
Implement an instance of Monad
instance Monad (StateX s) where
return a = StateX (\s → (a, s)) -- Keep the same state and a
(>>=) (StateX g) f = StateX (\s → let (a, ns) <- g s in runStateX (f a) ns
↑ ↑ ↑ ↑
| | | + → (a -> m b) a ⟹ m b
| | |
+ → f :: (a -> m b) | |
| |
| + → runStateX (m b) ⟹ \s → (b, s) ∵ runStateX (StateX f) = f ⟹ runStateX (StateX (\s → (b, s)) = \s → (b, s)
| ↑
| + → StateX s b = StateX(\s → (b, s))
| |----+-|
| ↓
| + → m
|
| |---------|
| |
| ↓
| + → m b
|
| ├- - - - + - - - - ┤
| |
| ↓
| runStateX (StateX f) = f
| ↓
| runStateX (StateX (\s → (b, s)) = \s → (b, s)
|
| runStateX (StateX (\ns → (b, s)) ns = \ns → (b, ns) ns ⟹ (b, ns)
|
|
|
|
|
+ → g::s → (a, s)