tipos tecnicas repeticion que patrones patron informatica informacion definicion busqueda arte algoritmos haskell pattern-matching

haskell - repeticion - tecnicas busqueda de patrones



¿Es posible exportar constructores para la coincidencia de patrones, pero no para la construcción, en Haskell Modules? (3)

Desde GHC 7.8 puede usar PatternSynonyms para exportar patrones independientes de los constructores. Entonces, un análogo a la respuesta de @ Lambdageek sería

{-# LANGUAGE PatternSynonyms #-} module ThingModule (Thing, pattern Foo, pattern Bar) where pattern Foo a <- RealFoo a pattern Bar a <- RealBar a data Thing = RealFoo Thing | RealBar Int

y

{-# LANGUAGE PatternSynonyms #-} module Main where import ThingModule doSomethingWithThing :: Thing -> Int doSomethingWithThing (Foo x) = doSomethingWithThing x doSomethingWithThing (Bar y) = y

Entonces parece constructores normales.

Si intenta utilizar Bar para construir un valor, obtiene

Main.hs:9:32: Bar used in an expression, but it''s a non-bidirectional pattern synonym In the expression: Bar y

Un tipo de datos vainilla en Haskell tiene cero o más constructores, cada uno de los cuales desempeña dos roles.

En las expresiones, admite la introducción, es una función de cero o más argumentos para el tipo de datos.

En los patrones, admite la eliminación, es como una función del tipo de datos a Maybe (tupla de tipos de argumentos).

¿Es posible que la firma de un módulo oculte el primero mientras se expone el último?

El caso de uso es el siguiente: tengo un tipo, T, cuyos tipos de constructores solos a veces se pueden usar para construir tonterías. Tengo funciones de construcción que pueden usarse para crear instancias del tipo que garanticen que no son absurdas. Tendría sentido esconder los constructores en este caso, pero aún sería útil para los llamadores para poder coincidir con los patrones garantizados, sin sentido, que construyen con las funciones de construcción.

Sospecho que esto es imposible, pero en caso de que alguien tenga una forma de hacerlo, pensé que lo haría.

Lo mejor es ocultar los constructores y crear un conjunto de funciones de T -> Tal vez (Esto, Eso), T -> Tal vez (El, Otro, Cosa), etc.


No puedes. Pero si solo hay un número razonable de constructores para su tipo T, es posible que desee ocultar los constructores y, en su lugar, proporcionar una función que haga la coincidencia de patrones con el mismo espíritu que maybe :: b -> (a -> b) -> Maybe a -> b .


Puede usar un tipo de vista y ver patrones para hacer lo que quiera:

module ThingModule (Thing, ThingView(..), view) where data Thing = Foo Thing | Bar Int data ThingView = FooV Thing | BarV Int view :: Thing -> ThingView view (Foo x) = FooV x view (Bar y) = BarV y

Tenga en cuenta que ThingView no es un tipo de datos recursivo: todos los constructores de valores se refieren a Thing . Así que ahora puedes exportar los constructores de ThingView de ThingView y mantener el resumen de Thing .

Use esto:

{-# LANGUAGE ViewPatterns #-} module Main where import ThingModule doSomethingWithThing :: Thing -> Int doSomethingWithThing(view -> FooV x) = doSomethingWithThing x doSomethingWithThing(view -> BarV y) = y

La nota de flecha es GHC''s View Patterns . Tenga en cuenta que requiere un lenguaje pragma.

Por supuesto, no está obligado a usar patrones de vista, puede simplemente hacer todo el desugaring a mano:

doSomethingWithThing :: Thing -> Int doSomethingWithThing = doIt . view where doIt (FooV x) = doSomethingWithThing x doIt (BarV y) = y

Más

De hecho, podemos hacerlo un poco mejor: no hay ninguna razón para duplicar todos los constructores de valores para Thing y ThingView

module ThingModule (ThingView(..), Thing, view) where newtype Thing = T {view :: ThingView Thing} data ThingView a = Foo a | Bar Int

Continúa utilizándolo de la misma manera que antes, pero ahora las combinaciones de patrones pueden usar Foo y Bar .

{-# LANGUAGE ViewPatterns #-} module Main where import ThingModule doSomethingWithThing :: Thing -> Int doSomethingWithThing(view -> Foo x) = doSomethingWithThing x doSomethingWithThing(view -> Bar y) = y