data - monads learn you a haskell
¿Dónde encontrar ejercicios de programación para los funtores aplicativos? (4)
He estado leyendo sobre funtores aplicativos, notablemente en la Perla funcional de McBride y Paterson. Pero me gustaría solidificar mi comprensión haciendo algunos ejercicios. Preferiría ejercicios de programación, pero los ejercicios de prueba también están bien. ¿Qué ejercicios me ayudarán a aprender a programar de manera efectiva con los funtores aplicativos?
Los ejercicios individuales están bien, como lo son los indicadores de los ejercicios enumerados en otra parte.
Mira la Typeclassopedia . Viene con una buena explicación desde cero y algunos ejercicios en el camino.
Por ejemplo: Funcionadores Aplicativos
Una buena forma de practicar es usar Parsec
en un estilo aplicativo en lugar de monádico. La mayoría de los analizadores son puramente aplicativos, por lo que no debería necesitar usar notación de do
nunca.
P.ej. para expresiones:
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
Parece divertido publicar algunas preguntas como respuesta. Este es divertido, en la interacción entre Applicative
y Traversable
, basado en sudoku.
(1) Considere
data Triple a = Tr a a a
Construir
instance Applicative Triple
instance Traversable Triple
de modo que la instancia Applicative
hace "vectorización" y la instancia Traversable
funciona de izquierda a derecha. No olvides construir una instancia de Functor
adecuada: comprueba que puedes extraerla de la instancia Traversable
o de Traversable
. Puedes encontrar
newtype I x = I {unI :: x}
útil para el último.
(2) Considere
newtype (:.) f g x = Comp {comp :: f (g x)}
Muestra esa
instance (Applicative f, Applicative g) => Applicative (f :. g)
instance (Traversable f, Traversable g) => Traversable (f :. g)
Ahora define
type Zone = Triple :. Triple
Supongamos que representamos una Board
como una zona vertical de zonas horizontales
type Board = Zone :. Zone
Muestre cómo reorganizarlo como una zona horizontal de zonas verticales, y como un cuadrado de cuadrados, utilizando la funcionalidad de traverse
.
(3) Considere
newtype Parse x = Parser {parse :: String -> [(x, String)]} deriving Monoid
o alguna otra construcción adecuada (teniendo en cuenta que el comportamiento de la biblioteca Monoid
para | Tal vez | es inapropiado). Construir
instance Applicative Parse
instance Alternative Parse -- just follow the `Monoid`
e implementar
ch :: (Char -> Bool) -> Parse Char
que consume y entrega un personaje si es aceptado por un predicado determinado.
(4) Implemente un analizador sintáctico que consuma cualquier cantidad de espacio en blanco, seguido de un solo dígito (0 representa espacios en blanco)
square :: Parse Int
Use pure
y traverse
para construir
board :: Parse (Board Int)
(5) Considere los funtores constantes
newtype K a x = K {unK :: a}
y construir
instance Monoid a => Applicative (K a)
luego usa traverse
para implementar
crush :: (Traversable f, Monoid b) => (a -> b) -> f a -> b
Construya envolturas de tipo nuevo para Bool
expresando sus estructuras monoidales conjuntivas y disyuntivas. Utilice crush
para implementar versiones de any
que funcione para cualquier functor de Traversable
.
(6) Implementar
duplicates :: (Traversable f, Eq a) => f a -> [a]
computar la lista de valores que ocurren más de una vez. (No es completamente trivial.) (Hay una forma encantadora de hacer esto usando cálculo diferencial, pero esa es otra historia).
(7) Implementar
complete :: Board Int -> Bool
ok :: Board Int -> Bool
que verifican si una placa está (1) llena solamente de dígitos en [1..9] y (2) sin duplicados en ninguna fila, columna o caja.