2012-04-20 5 views
27

필자는 맥브라이드 (McBride)와 패터슨 (Paterson)의 Functional Pearl에서 응용 펑터 (functor)에 대해 읽었습니다. 그러나 나는 약간의 연습을함으로써 나의 이해를 확고히하고 싶습니다. 나는 프로그래밍 연습을 선호하지만 증명 연습도 괜찮습니다. 어떤 운동을하면 적용 가능한 펑터로 효과적으로 프로그램하는 법을 배울 수 있습니까?적용 가능한 펑터에 대한 프로그래밍 연습을 어디에서 찾을 수 있습니까?

다른 연습 문제는 다른 곳에서 연습 문제를 가리키는 포인터와 마찬가지로 정상입니다.

+3

연습을 제안 할 수는 없지만 모나드가 아닌 응용 펑터를 볼 수는 있습니다. (중요한 질문은 "모나드보다 강력하지 않을 때 응용 펑터를 디자인하는 이유는 무엇입니까?"). 멀티 패러다임 적용 (Paterson과 McBride)은 하나이고 Doaitse Swierstra의 파서, Andy Gill과 Kevin Matledge의 칠판에 애니메이션 하나 _Active_가 있습니다. Andy Gill과 동료 Kansas Lava는 응용 펑터를 기반으로합니다. –

답변

20

답으로 몇 가지 질문을 게시하는 것이 즐겁습니다. 스도쿠를 기초로 한 ApplicativeTraversable 사이의 상호 작용에 관한 재미있는 이야기입니다.

(1)

data Triple a = Tr a a a 

instance Applicative Triple 
instance Traversable Triple 

를 구축 고려 그래서 Applicative 인스턴스가 "벡터화"수행과 Traversable 인스턴스가 왼쪽에서 오른쪽으로 작동합니다. 적절한 Functor 인스턴스를 만드는 것을 잊지 마세요. Applicative 또는 Traversable 인스턴스에서 추출 할 수 있는지 확인하십시오. 당신은 찾을 수 있습니다

newtype I x = I {unI :: x} 

후자에 유용합니다.

(2)

newtype (:.) f g x = Comp {comp :: f (g x)} 

지금

instance (Applicative f, Applicative g) => Applicative (f :. g) 
instance (Traversable f, Traversable g) => Traversable (f :. g) 

우리가 수평 영역

,495 수직 영역으로서 Board를 나타내는

type Zone = Triple :. Triple 

가정하자 정의하는 것이 확인 고려

traverse의 기능을 사용하여 수직 영역의 수평 영역으로, 사각형의 정사각형으로 재정렬하는 방법을 보여줍니다.

(3)

newtype Parse x = Parser {parse :: String -> [(x, String)]} deriving Monoid 

또는 (| 어쩌면 | 부적절한의 라이브러리 Monoid 동작 것을주의) 일부 다른 적절한 구조를 생각해 보자.

instance Applicative Parse 
instance Alternative Parse -- just follow the `Monoid` 

를 구축하고 소모가 주어진 조건에 의해 허용되는 경우 문자를 제공

ch :: (Char -> Bool) -> Parse Char 

구현합니다.

(4)

square :: Parse Int 

사용 puretraverse 구축 (0은 공백을 나타낸다) 한 다음에 숫자 공백의 모든 양을 소비하는 파서를 구현

board :: Parse (Board Int) 

(5) 상수 펑터를 고려하십시오.

newtype K a x = K {unK :: a} 

및 constru CT

instance Monoid a => Applicative (K a) 

crush :: (Traversable f, Monoid b) => (a -> b) -> f a -> b 

가 접속어와 논리합 모노 이드 구조를 표현 Bool에 대한 newtype 래퍼를 구축 구현하는 traverse를 사용합니다. Traversable 펑터에서 작동하는 anyall의 버전을 구현하려면 crush을 사용하십시오.

(6) 번 이상 발생할 값 목록을 계산

duplicates :: (Traversable f, Eq a) => f a -> [a] 

구현. (완전히 사소한하지 않습니다.) (이이 사용하는 차동 미적분을 할 수있는 멋진 방법입니다,하지만 그건 또 다른 이야기입니다.)

(7) 보드가 있는지 확인

complete :: Board Int -> Bool 
ok :: Board Int -> Bool 

를 구현 (1) 전체 단지 행, 열 또는 상자에 중복이없는 [1..9] 및 (2)의 자릿수

+0

위대한 excercises! – luqui

5

Typeclassopedia을 확인하십시오. 그것은 기초부터 좋은 설명과 함께 몇 가지 연습을 함께 제공됩니다. 예를 들어

4
+0

이 링크는 죽었지 만 [이것은 인터넷 아카이브 웨이 백 컴퓨터] 페이지입니다 (https://web.archive.org/web/*/http://www.cis.upenn.edu/~cis194/lectures/). *) : [Functors] (https://web.archive.org/web/20130803145920/http://www.cis.upenn.edu/~cis194/lectures/09-functors.html); [응용 펑터] (https://web.archive.org/web/20130803134207/http://www.cis.upenn.edu/~cis194/lectures/10-applicative.html) –

12

좋은 방법은 연습 오히려 모나드 스타일보다는 실용적으로 Parsec을 사용하는 것입니다. 대부분의 파서는 순수하게 적용 할 수 있으므로 do 표기법을 사용할 필요가 없습니다.

예 : 표현식 :

import qualified Text.Parsec as P 
import qualified Text.Parsec.Token as P 
import Control.Applicative 

data Expr = Number Int | Plus Expr Expr 

lex = P.makeTokenParser ... -- language config 

expr = number <|> plus 
    where 
    number = Number <$> P.integer lex 
    plus = Plus <$> number <* P.symbol lex "+" <*> expr 
+0

나는 호기심 - 적용 할 수있는 펑터로 해석 할 수 없지만 모나드로 할 수있는 몇 가지 일반적인 또는 적어도 합리적인 예제를 제공 할 수 있습니까? –

+7

@TikhonJelvis, * 형식적으로 * 이들은 유한 한 알파벳 이상으로 권력면에서 유사하지만 병리학 적 방법으로 (그들은 모두 무한 문법을 ​​지원합니다). 그러나 모나드가 필요한 곳의 좋은 예는 구문 분석에서 나중에 고려해야 할 새로운 문법적 구성을 정의 할 수있는 언어가있는 경우입니다.'Applicative '는 * content *를 기반으로 구조를 변경할 수 없습니다. – luqui

+0

+1 제목을 보았을 때 곧 파섹을 생각했습니다. 흥미롭고 사소하면서도 단순한 문제를 해결하는 연습 방법입니다. –