Кажется забавным опубликовать некоторые вопросы в качестве ответа. Это весело, взаимодействие между 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
для | Может быть | неуместно).Построить
instance Applicative Parse
instance Alternative Parse -- just follow the `Monoid`
и осуществлять
ch :: (Char -> Bool) -> Parse Char
, который потребляет и поставляет характер, если оно принимается по заданному предикату.
(4) Выполнить синтаксический анализатор, который потребляет любое количество пробелов, за которым следует одна цифра (0 представляет пробелы)
square :: Parse Int
Использование pure
и traverse
построить
board :: Parse (Board Int)
(5) Рассмотрим постоянные функторы
newtype K a x = K {unK :: a}
и constru кт
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), лишенных дубликатов в любой строке, столбце или поле.
Я не могу предложить упражнения, но вы можете посмотреть на аппликативные функторы, которые не являются монадами (как представляется, главный вопрос: «зачем создавать аппликативный функтор, когда он менее мощный, чем монада?»). Применения с несколькими ошибками (в Патерсоне и Макбрайде) - это один, есть парсеры Doaitse Swierstra, анимационный один _Active_ в классной доске Andy Gill и Kevin Matledge, плюс я думаю, что Энди Гилл и его коллеги Kansas Lava основаны на аппликативном функторе. –