2016-10-15 4 views
6

Haskell Book, "22 장. 독자"의 연습 문제가 있습니다. 운동은 "리더의 실용적 구현"라고하고 다음과 같은 수 있습니다 :독자 r에 대한 Applicative 인스턴스를 쓸 때 <*>을 쓰는 방법

{-# LANGUAGE InstanceSigs #-} 

newtype Reader r a = 
    Reader { runReader :: r -> a } 

instance Applicative (Reader r) where 
    pure :: a -> Reader r a 
    pure a = Reader $ ??? 

    (<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b 
    (Reader rab) <*> (Reader ra) = Reader $ \r -> ??? 

그렇지 않으면 GHC 아니오 "불평했기 때문에 (나는의 Functor 인스턴스를 쓴 나는 또한 Functor 인스턴스를 작성 후 pure을 쓸 수 있었다) "‘Applicative (Reader r)’의 인스턴스 선언에서 인스턴스 선언의 수퍼 클래스에서 발생하는 (Functor (Reader r)) …에 대한 예 :

{-# LANGUAGE InstanceSigs #-} 

newtype Reader r a = 
    Reader { runReader :: r -> a } 

instance Functor (Reader r) where 
    fmap f (Reader x) = Reader (f . x) 

instance Applicative (Reader r) where 
    pure :: a -> Reader r a 
    pure a = Reader $ \_ -> a 

    (<*>) :: Reader r (a -> b) -> Reader r a -> Reader r b 
    (Reader rab) <*> (Reader ra) = Reader $ \r -> ??? 

하지만이 ??? 부분에 붙어있어. 우리는 당신이해야 할 일을 설명 것, 적용 함수의 정의는 당신을 위해 시작있어

당신은 코드를 작성 :

이 책은 다음과 같은 힌트를 제공합니다. 위의 판독기 유형 의 압축을 풀면 다음과 같이 표시됩니다.

<*> :: (r -> a -> b) 
    -> (r -> a) 
    -> (r -> b) 

-- contrast this with the type of fmap 

fmap :: (a -> b) 
    -> (r -> a) 
    -> (r -> b) 

그래서 무엇이 다른가요? 차이점은 apply이며 fmap과 달리 r 유형의 인수도 필요합니다.

확인하십시오.

예, 그렇지만 어떻게해야합니까? 형식화 된 구멍을 사용하면 컴파일러에서 ??? 유형이 b이어야 함을 알려줍니다. 그러나 나는 r을 취하고 b 타입을 반환하는 람다 식을 어떻게 만들 수 있는지 알 수 없다. rabra이 주어진다. 당신이 범위에있는 조각을 보면

+0

당신은 또한 그 책을 사지 않을 우리들을 위해'Reader' 데이터 유형의 정의를 제공 할 수 있습니까? –

+0

@Rhymoid 좀 가혹합니다. 어쨌든'Reader'는 일반 지식입니다. – duplode

+0

누락 된 리더 유형에 대해 사과드립니다. 위 질문에 추가했습니다. –

답변

7

,

rab :: r -> (a -> b) 
ra :: r -> a 
r :: r 

b의 목표 유형, 당신은 유일한 방법은 당신이 두 개의 인수에 rab을 적용하여하는 b를 얻을 수 있음을 알 수있다.

Reader rab <*> Reader ra = Reader $ \r -> rab _ _ 

이제 첫 번째 구멍은 r의 유형이 있고, 당신은 단지 범위에서 하나의 r 있습니다.

Reader rab <*> Reader ra = Reader $ \r -> rab r _ 

나머지 홀의 유형은 a입니다. 당신이 범위에있는 유일한 ara의 반환 값입니다

Reader rab <*> Reader ra = Reader $ \r -> rab r (ra _) 

ra의 인수는 다시 한번 하나만 선택의 여지가있는 위해 r을해야합니다. rabra 모두 인수로 r를받을 수

Reader rab <*> Reader ra = Reader $ \r -> rab r (ra r) 

알 수 있습니다.구성된 Reader 계산의 모든 단계는 동일한 환경에 액세스 할 수 있습니다.

덧붙여서이 정의는 을 S combinator (및 pureK)과 동일하게 만듭니다.