몇 가지 대체를 수행하면 효과가 있다는 것을 확신 할 수 있습니다. 먼저 createUser
의 서명을보십시오. 이제 Reader
의 정의를 "풀다"하자
createUser :: Reader Permissions (Maybe User)
{- definition of Reader -}
createUser :: ReaderT Permissions Identity (Maybe User)
ReaderT
유형은 하나의 데이터 생성자가 있습니다 ReaderT (r -> m a)
입력 ReaderT (Permissions -> Identity (Maybe User))
의 값으로 평가되는 용어입니다 createUser
을 의미한다. 보시다시피, 그것은 단지 ReaderT
태그가 붙은 함수입니다.얇은 공기에서 아무것도 만들 필요가 없지만 해당 함수가 호출 될 때 Permissions
유형의 값을받습니다.
이제 문제가있는 라인을 살펴 보겠습니다. 당신은 do
표기 그냥 문법 설탕, 그리고 표현임을 알고
do permissions <- ask
if hasPermission "admin" permissions
then map Just newUser
else pure Nothing
desugars
ask >>= \permissions ->
if hasPermission "admin" permissions
then map Just newUser
else pure Nothing
이가 무엇을 이해하려면, 당신은
ask
,
>>=
및
pure
의 정의를 조회해야합니다
ReaderT
입니다. 의는 대체의 또 다른 라운드를 수행 할 수 있습니다 :
ask >>= \permissions -> ...
{- definition of ask for ReaderT -}
ReaderT pure >>= \permissions -> ...
{- definition of >>= for ReaderT -}
ReaderT \r ->
pure r >>= \a -> case (\permissions -> ...) a of ReaderT f -> f r
{- function application -}
ReaderT \r ->
pure r >>= \a ->
case (if hasPermission "admin" a
then map Just newUser
else pure Nothing) of ReaderT f -> f r
{- definition of pure for Identity -}
ReaderT \r ->
Identity r >>= \a ->
case (if hasPermission "admin" a
then map Just newUser
else pure Nothing) of ReaderT f -> f r
{- definition of >>= for Identity -}
ReaderT \r ->
(\a ->
case (if hasPermission "admin" a
then map Just newUser
else pure Nothing) of ReaderT f -> f r) r
{- function application -}
ReaderT \r ->
case (if hasPermission "admin" r
then map Just newUser
else pure Nothing) of ReaderT f -> f r
당신이 볼 수 있듯이, createUser
이 명확하게 표현을 통해 값 (이하 "환경") 스레드 ReaderT
래핑 단지 기능입니다. runReader
함수를 랩핑 해제하고 제공된 인수를 호출
runReader :: forall r a. Reader r a -> r -> a
runReader (ReaderT f) r = f r
'리더 b'는의'래퍼입니다 -> b'. 그래서'ask :: forall a. Reader a는 궁극적으로'forall a 유형의 값입니다. a -> a', 주위에 래퍼가 있습니다. –