tipos simbolos pattern opciones hacer funciones ejemplos como ciclos haskell pointfree

simbolos - pattern matching haskell



Aplicando mĂșltiples funciones al mismo valor de estilo sin puntos en Haskell (4)

Un día me aburrí y quería ejercitar mi cerebro, así que decidí resolver los 99 problemas de Haskell, pero me limité a hacerlo en un estilo sin puntos. Un problema que parece surgir mucho cuando estoy haciendo cosas en un estilo sin puntos es el siguiente: ¿cómo se aplican varias funciones al mismo valor y se mantiene cada resultado como una entidad independiente? Usando notación apuntada:

foobar x = [id x, reverse x]

Y lo que he encontrado hasta ahora en notación sin puntos:

foobar'' = `map` [id, reverse] ($ x)

Parece que no puedo sacar esa x al final de allí.


Hay algunos combinadores idiomáticos básicos que aparecen repetidamente y se reimplementan con varios conceptos y bibliotecas superiores, pero que son esencialmente muy simples. Los nombres pueden variar, y algunos son implementables en términos de otros:

fork (f,g) x = (f x, g x) -- == (f &&& g) prod (f,g) x = (f $ fst x, g $ snd x) -- == (f *** g) pmap f (x,y) = (f x, f y) -- == (f *** f) dup x = (x,x)

Por supuesto, uncurry f (x,y) == fxy se usa mucho con estos también.

&&& y *** se definen en Control.Arrow , así como first y second . Luego prod (f,id) == first f , prod(id,g) == second g etc. etc.

Así se convierte tu foobar

foobar = (/(a,b)->[a,b]) . fork (id,reverse) = (/(a,b)->[a,b]) . (id &&& reverse) = (/(a,b)->[a,b]) . (id *** reverse) . dup = join $ curry ( (/(a,b)->[a,b]) . second reverse)

Para el último también necesita importar Control.Monad y Control.Monad.Instances . Véase también esta pregunta .

edición tardía: también, usando Control.Applicative como se indica en la respuesta de ertes ,

= (:) <*> ((:[]) . reverse)


Le interesará la instancia de Applicative de la mónada lectora:

instance Applicative (e ->)

Usándolo puedes distribuir fácilmente un argumento:

liftA2 (+) sin cos 3

Aquí, sin y cos son funciones, las cuales reciben el valor 3. Los resultados individuales se combinan usando (+) . Puede combinar esto aún más con la instancia de Category de (->) , pero las versiones especializadas de cource de (.) Y id ya están definidas en Prelude .

Antecedentes: la instancia de Applicative para (e ->) realmente representa el cálculo de SKI, donde (<*>) es el combinador S y pure es el combinator K. S se usa precisamente para distribuir un argumento a dos funciones:

S f g x = f x (g x)

Toma una aplicación de función ( fg ) y hace que ambos dependan del valor x ( (fx) (gx) ).


Otros ya han publicado cómo puede hacerlo utilizando la mónada Reader , pero esa no es la única manera. Resulta que tu segunda función está bastante cerca. Creo que querías publicar

foobar'' x = (`map` [id, reverse]) ($ x)

Como la x ya está cerca de la posición más a la derecha, ya casi estás allí. Primero, transforme la sección ($ x) en una función, porque es un poco más fácil trabajar con:

-- by the definition of a right operator section foobar''2 x = (`map` [id, reverse]) (/y -> ($) y x)

Luego elimine la x del cuerpo lambda poniendo una nueva variable en su alcance y aplicando la función a x

-- lambda abstraction I think... foobar''2 x = (`map` [id, reverse]) $ (/z y -> ($) y z) x

Reescriba esta aplicación como una composición de función, y luego puede eta reducir:

-- by definition of ''.'' foobar''3 x = (`map` [id, reverse]) . (/z y -> ($) y z) $ x -- eta reduction foobar''4 = (`map` [id, reverse]) . (/z y -> ($) y z)

Finalmente, note que podemos reemplazar la lambda con una función.

-- by definition of `flip` foobar''5 = (`map` [id,reverse]) . flip ($)

y tienes una forma libre de puntos.


Usa sequence :

> let foobar'' = sequence [id, reverse] > foobar'' "abcde" ["abcde","edcba"]