2012-07-19 28 views
7

Así que sigo oyendo mucho sobre la programación sin puntos y decidí hacer un pequeño experimento para probar mi comprensión. Esto implicaba tomar una función puntiaguda para calcular el factorial de un número y convertirlo en una forma libre de puntos. Logré hacerlo, pero el resultado sin puntaje es mucho menos legible que el resultado puntiagudo.Notación libre de puntos, recurrencia y coincidencia de patrones

-- pointed 
fact 0 = 1 
fact n = n * (fact (n-1)) 
-- point free 
fact' = foldr1 (*) . takeWhile ((<) 0) . iterate (flip (-) 1) 

¿Me falta algo esencial para señalar la notación libre o es tan legible como ciertas transformaciones? Para mí, parece que una gran parte de la función fact es la coincidencia de patrones en cero, y de hecho, la coincidencia de patrones es una de las principales razones por las que amo a Haskell. Sin embargo, la notación libre de puntos parece no permitirlo por completo, junto con algunas otras cosas que son extremadamente útiles, como la comprensión de listas.

+6

prefiero 'producto. enumFromTo 1'. – Vitus

+5

[Evolución de un programador Haskell] (http://www.willamette.edu/~fruehr/haskell/evolution.html) – sdcvvc

+2

Espera. ¿Esperaste _readability_ de _sintaxis sin puntos_? Decir ah. Jaja. Hahahahaha. No. –

Respuesta

15

El factorial canónica en forma pointfree es:

fact = product . enumFromTo 1 

(lo que equivale a fact n = product [1..n])

me parece que esto es muy fácil de leer. Sin embargo, me acuerdo en que la versión original:

fact 0 = 1 
fact n = n * (fact (n-1)) 

coincide con la definición muy bien y también es fácil de leer.

El punto (¡ja!) De la forma pointfree es para que sea fácil razonar sobre funciones como la composición de otras funciones. Sin embargo, la función factorial no es realmente un excelente candidato para este tipo de razonamiento.

La decisión es suya, obviamente.

+0

Interesante, no sabía que existía una función como enumFromTo. Entonces, ¿qué pasa con la coincidencia de patrones? Por necesidad, eso requiere una notación puntiaguda. ¿Sostendría que eso no cae bajo los límites del razonamiento sobre las funciones como composición? – Dwilson

+0

@Dwilson: es parte de la clase de tipo 'Enum': http: //hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html # t: Enum –

+3

@Dwilson: Puede traducir la coincidencia de patrones en notación sin puntos. Solo mira funciones como 'quizás' o' cualquiera'; tomando 'cualquiera' como ejemplo: le das dos funciones, una para 'Izquierda' y la segunda para el caso 'Derecho' y eso es todo. De hecho, puede construir fácilmente esas funciones porque son parte del isomorfismo entre ADT y su codificación de la Iglesia. Las listas probablemente no tienen esa función, pero es fácil de implementar: 'listcase [] z f = z; listcase (x: xs) z f = f x xs'. – Vitus

2

Para cada tipo de datos de unión algebraica debe existir su función de discriminación de casos tipo que encapsula la coincidencia de patrones para ese tipo. Ya tenemos

either :: (a -> c) -> (b -> c) -> Either a b -> c 
maybe :: b -> (a -> b) -> Maybe a -> b 

Del mismo modo debe ser tal función para números,

num :: (Num a) => b -> (a -> b) -> a -> b 
num z nz 0 = z 
num z nz x = nz x 

por lo que podemos escribir

import Control.Applicative 
import Data.Function 

fact :: (Num a) => a -> a 
fact x = num 1 (\x-> (*) (fact (pred x)) x) x 
     = num 1 ((*) =<< (fact.pred)) x 

decir

fact = (num 1 . ((*) =<<) . (. pred)) fact 
     = fix (num 1 . ((*) =<<) . (. pred)) 
+1

Diablos, ahora eso es mucho más legible que 'producto. enumFromTo 1' ... – leftaroundabout

+1

@leftaroundabout ¿hubo un ':)' en algún lugar? .... :) el punto principal que quería hacer era en realidad con la función 'num'. pero también, para responder al título más de cerca, no se trata del 'factorial' per se ... –

+0

Si bien es menos legible, esto es interesante. ¿Podría elaborar un poco más sobre la primera oración y qué significa "num" con respecto a eso, específicamente la parte de la función del discriminador de casos tipo? – Dwilson

Cuestiones relacionadas