2012-04-20 12 views
27

私は、特にMcBrideとPatersonのFunctional Pearlのアプリケーションファンクタについて読んできました。しかし、私はいくつかの練習をして私の理解を固めたいと思います。私はプログラミング演習を好むだろうが、実証演習もOKです。 練習問題を教えてください。アプリケーションファンクタのプログラミング演習はどこにありますか?

個々の演習は、別の場所にリストされている演習の指針と同様です。

+3

私は練習問題を提案することはできませんが、モナドではないアプリケーションファンクタを見ることができます(重要な質問は「なぜモナドよりも強力ではない場合に、アプリケーションファンクタを設計するのですか? Andy GillとKevin MatledgeのChalkboardのアニメーションの1つであるAnda Gillと同僚のKansas Lavaは、応用ファンクタをベースにしていると考えています(PatersonとMcBrideのマルチエラーアプリケーションは1つです)。 –

答えて

20

答えとしていくつかの質問を投稿すると面白いようです。これは、スードクに基づいて、ApplicativeTraversableの間の相互作用の楽しいものです。 Applicativeインスタンスは、 "ベクトル" とTraversableインスタンスが左から右に動作しないように

(1)

data Triple a = Tr a a a 

instance Applicative Triple 
instance Traversable Triple 

を構築することを検討します。適切なFunctorインスタンスを構築することを忘れないでください:ApplicativeインスタンスまたはTraversableインスタンスのいずれかからこれを抽出できることを確認してください。あなたは見つけることができます

newtype I x = I {unI :: x} 

は、後者に役立ちます。

(2)

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

すぐ

type Zone = Triple :. Triple 

を定義

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

我々は、水平ゾーンの垂直ゾーン

として Boardを表すと仮定していることを表示検討

水平ゾーンの水平ゾーンとして再配置する方法と、正方形の正方形としてtraverseの機能を使用して再配置する方法を示します。

(3)(不適切である| |たぶんためのライブラリMonoid行動があることに留意)

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

またはいくつかの他の適切な構造を考えてみましょう。

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

を構築し、それが与えられた述語によって受け入れられた場合、文字を消費し、提供

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

を実装します。

(4)

board :: Parse (Board Int) 

(5)を構築する

square :: Parse Int 

使用puretraverse(0は空白を表す)単一の数字が続く、空白の任意の量を消費するパーサを実装定数ファンクタを考える。

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 

はその連言と選言モノイド構造を表現するためのBoolnewtypeラッパーを構築し実装するため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

すばらしいエクササイズ! – 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'は、*コンテンツ*に基づいて構造体を変更することはできません、' Monad' can。 – luqui

+0

+1タイトルを見たとき、私はすぐにパーセルを考えました。これは面白くて重要ではない単純な問題を解決する練習に最適な方法です。 –

関連する問題