特に McBride と Paterson による Functional Pearl で、Applicative functor について読んでいます。しかし、いくつかの演習を行って理解を固めたいと思います。私はプログラミングの演習が好きですが、証明の演習も問題ありません。 アプリカティブ ファンクターを使った効果的なプログラミングを学ぶには、どのような演習が役立ちますか?
個々のエクササイズは、他の場所にリストされているエクササイズへのポインターと同様に問題ありません。
特に McBride と Paterson による Functional Pearl で、Applicative functor について読んでいます。しかし、いくつかの演習を行って理解を固めたいと思います。私はプログラミングの演習が好きですが、証明の演習も問題ありません。 アプリカティブ ファンクターを使った効果的なプログラミングを学ぶには、どのような演習が役立ちますか?
個々のエクササイズは、他の場所にリストされているエクササイズへのポインターと同様に問題ありません。
答えとしていくつかの質問を投稿するのは面白いようです。これは、数独に基づいたApplicative
との間の相互作用に関する楽しいものです。Traversable
(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)
今定義する
type Zone = Triple :. Triple
Board
を水平ゾーンの垂直ゾーンとして表すとします。
type Board = Zone :. Zone
の機能を使用して、垂直ゾーンの水平ゾーンとして、および正方形の正方形として再配置する方法を示しますtraverse
。
(3)検討する
newtype Parse x = Parser {parse :: String -> [(x, String)]} deriving Monoid
または他の適切な構造(Monoid
| Maybe |のライブラリの動作が不適切であることに注意してください)。構築する
instance Applicative Parse
instance Alternative Parse -- just follow the `Monoid`
実装します
ch :: (Char -> Bool) -> Parse Char
これは、特定の述語によって受け入れられた場合に文字を消費して配信します。
(4)任意の量の空白を消費するパーサーを実装し、その後に1桁の数字を続けます(0はブランクを表します)
square :: Parse Int
およびを使用pure
しtraverse
て構築する
board :: Parse (Board Int)
(5)定数関手を考慮する
newtype K a x = K {unK :: a}
構築します
instance Monoid a => Applicative (K a)
次に、を使用traverse
して実装します
crush :: (Traversable f, Monoid b) => (a -> b) -> f a -> b
接続詞および論理和のモノイド構造を表現するためnewtype
のラッパーを作成します。のバージョンを実装するためにBool
使用し、どのファンクターでも機能します。crush
any
all
Traversable
(6)実装
duplicates :: (Traversable f, Eq a) => f a -> [a]
複数回発生する値のリストを計算します。(完全に些細なことではありません。)(微分計算を使用してこれを行うための素敵な方法がありますが、それは別の話です。)
(7)実装
complete :: Board Int -> Bool
ok :: Board Int -> Bool
これは、ボードが(1)[1..9]の数字のみでいっぱいであり、(2)行、列、またはボックスに重複がないかどうかをチェックします。
練習するのに最適な方法は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
Typeclassopediaをチェックしてください。それはゼロからの良い説明と途中でいくつかの練習が付属しています。