2010-08-20 3 views
12

Wadler의 논문을 모나드에서 읽은 후 필자는 자신이 묘사 한 모나드 각각에 대해 펑터 (functor)와 적용 가능한 인스턴스를 정의하여보다 자세히 작업하기로 결정했습니다.Haskell의 Functor/Applicative 인스턴스

type M a = State -> (a, State) 
type State = Int 

Wadler은 상태 모나드를 정의하는 데 사용하는 유형의 동의어를 사용하여, 나는 다음과 같은이 (사용 관련 이름을 그래서 나중에에 newtype이란 선언을 정의 할 수 있습니다).

fmap' :: (a -> b) -> M a -> M b 
fmap' f m = \st -> let (a, s) = m st in (f a, s) 

pure' :: a -> M a 
pure' a = \st -> (a, st) 

(<@>) :: M (a -> b) -> M a -> M b 
sf <@> sv = \st -> let (f, st1) = sf st 
         (a, st2) = sv st1 
        in (f a, st2) 

return' :: a -> M a 
return' a = pure' a 

bind :: M a -> (a -> M b) -> M b 
m `bind` f = \st -> let (a, st1) = m st 
         (b, st2) = f a st1 
        in (b, st2) 

나는 newtype은 선언의 형식에 생성자를 사용하도록 전환, 예를 들어,

newtype S a = S (State -> (a, State)) 

모든 것이 무너진다. 모든

instance Functor S where 
fmap f (S m) = S (\st -> let (a, s) = m st in (f a, s)) 

instance Applicative S where 
pure a = S (\st -> (a, st)) 

그러나 아무것도 때문에 람다 표현식 유형 생성자 내부에 숨겨져 있다는 사실 GHC에서 실행하지 예를 들어, 단지 약간의 수정이다. 지금은 볼 수있는 유일한 해결책은 함수를 정의하는 것입니다

예를 들어 값을 '성'으로의 바인딩 실제로 반환하기 위해,에
isntThisAnnoying s (S m) = m s 

,

fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s)) 

이 작업을 수행하는 또 다른 방법이 있나요 이러한 보조 기능을 사용하지 않습니까? 당신이 here을 보면

답변

11

, 당신은 그들이 이런 식으로 정의하는 것을 볼 수 있습니다 : 내부 람다에 이름을 지정하는

newtype State s a = State { runState :: (s -> (a,s)) } 

있도록한다.

+2

'runState = flip isntThisAnnoying'을 의미합니다. – kennytm

+1

좋습니다 - 보조 함수가 여전히 필요하지만, 레코드를 사용하여 형식을 정의하여 함수를 무료로 가져올 수 있습니다. 그렇다면 'runState'또는 'run'과 같은 함수를 사용하지 않는 방법은 없다는 것입니다. 감사. – danportin

+0

그것이 함수라고 생각하면 구조체 접근 자라고 생각하면됩니다. :-) –

4

일반적인 방법은 newtype newtype S a = S {runState : State -> (a, State)}을 정의하는 것입니다. 그런 다음 isntThisAnnoying s (S m) 대신 runState t s을 쓸 수 있습니다. tS m과 같습니다.
입력 동의어는 typecass 인스턴스가 될 수 없기 때문에 newtype을 사용해야합니다.

관련 문제