그래서 우리는 결론을 내릴 수있는 첫 번째 일은이 다음과 같은 기능의 특별한 경우로 볼 수 있다는 것입니다 몇가지 종류.
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g = (>>) <$> f <*> g
...또는, 당신이 선호하는 경우 : 물론
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth = liftA2 (>>)
, liftA2
가 liftM2
에 해당 다른 모나드에 모나드에 대한 조작을 리프팅 모나드 변압기 함께 할 수있는 뭔가가 그래서 만약 당신이 궁금 할 것이다; 일반적 관계에 불편이 있지만,이 경우에는이 같은 것을주고, 쉽게 작동합니다
doBoth :: (Monad m) => ReaderT a m b -> ReaderT a m c -> ReaderT a m c
doBoth = (>>)
... 모듈 적절한 포장 등의 과정. 원래 버전으로 되돌리려면 원래 return
의 사용은 ReaderT a m a
유형의 코드 여야합니다. 판독기 모나드의 경우 ask
함수로 인식하기가 너무 어려워서는 안됩니다.
다른 관점 (Monad m) => a -> m b
같은 유형의 기능이 훨씬 순수 기능처럼 직접 구성 될 수 있다는 것을 인식하는 것입니다. 함수 (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
은 함수 구성 (.) :: (b -> c) -> (a -> b) -> (a -> c)
과 직접적으로 동일하거나 대신 Control.Category
및 newtype
래퍼 Kleisli
을 사용하여 일반적인 방법으로 동일한 작업을 수행 할 수 있습니다.
우리는 여전히 인수를 분할해야하지만 여기에 실제로 필요한 것은 Category
에는없는 분기 구성입니다. 다음과 같이 우리가 기능을 다시시키는뿐만 아니라 우리가 (&&&)
얻을 Control.Arrow
를 사용하여 :
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a (b, c)
doBoth f g = f &&& g
을 우리가 처음 Kleisli 화살표의 결과에 대해 상관하지 않기 때문에, 유일한 부작용은 우리의 절반을 삭제할 수 있습니다 명백한 방법으로 튜플 :
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a c
doBoth f g = f &&& g >>> arr snd
일반적인 형식으로 우리를 되 찾을 수 있습니다. 원래에 전문의 return
는 이제 단순히 id
됩니다 : 일반 기능 Arrow
의 당신이 유형의 서명을 일반화하면 정의는 위뿐만 아니라이 작품 또한
constKleisli :: (Monad m) => Kleisli m a b -> Kleisli m a a
constKleisli f = f &&& id >>> arr snd
입니다. 그러나, 다음과 같이 순수 기능에 대한 결과의 정의를 확장하고 단순화하는 계몽 할 수있다 :
\f x -> (f &&& id >>> arr snd) x
\f x -> (snd . (\y -> (f y, id y))) x
\f x -> (\y -> snd (f y, y)) x
\f x -> (\y -> y) x
\f x -> x
.
예상대로 flip const
으로 돌아 왔습니다.
한마디로
, 함수 중 하나 (>>)
또는 flip const
에 대한 몇 가지 변화가 있지만 그 차이에 의존하는 방법으로 - ReaderT
환경과 기본 모나드의 (>>)
모두 사용 전, 후자의 사용 특정 Arrow
의 암시 적 부작용 및 특정 효과 순서로 Arrow
부작용이 발생할 것으로 예상됩니다. 이러한 세부 사항 때문에 일반화 또는 단순화가 가능하지는 않습니다. 어떤 의미에서는 사용하는 정의가 정확히 필요한만큼 간단하므로 내가 지정한 대체 정의가 더 길거나 줄 바꿈 및 줄 바꿈을 필요로합니다.
이와 같은 기능은 일종의 "모나드 유틸리티 라이브러리"에 자연스럽게 추가됩니다. Control.Monad
은 이러한 라인을 따라 일부 결합자를 제공하지만, 포괄적 인 것은 아니므로 표준 라이브러리에서이 함수의 변형을 발견하거나 회수 할 수 없었습니다. 그러나 나는 하나 또는 그 이상의 유틸리티 라이브러리에서 hackage를 발견하게되어 전혀 놀랄 일이 아니다.
대부분 존재 여부에 대한 질문이 없기 때문에, 관련 개념에 대한 위의 논의에서 취할 수있는 것 이상으로 많은 이름을 붙일 수는 없습니다.
마지막으로, 주요 목표가 무엇이든 상관없이 표현식을 실행 한 이후 모나드 표현식의 결과에 따라 함수에 제어 흐름 선택 항목이 없음을 유의하십시오. 매개 변수 내용 (예 : Monad m => m a
에 a
유형의 항목)과 독립적 인 계산 구조를 갖는 것은 일반적으로 Monad
이 실제로 필요하지 않으며 더 일반적인 개념 인 Applicative
으로 얻을 수 있다는 신호입니다.
일반 펑터를 사용하여이 함수를 정의 할 수있을 것 같습니다 :'constF :: Functor f => (a -> f b) -> a -> f a; constF f a = a <$ f a' – fuz
@FUZxxl, 이것도 잘 작동합니다. 덕분에 ... const 이름을 올바르게 사용 했나요? –
무엇을 의미합니까? – fuz