Considere un tipo de fecha y hora donde la fecha debe estar presente, pero la parte de tiempo en segundos es opcional. Si la parte de tiempo está allí, también puede haber una parte de milisegundos opcional. Si hay milisegundos, también puede haber una parte de nanosegundos.Datos "dependientes opcionales" en Haskell
Hay muchas maneras de hacer frente a esto, por ejemplo .:
--rely on smart constructors
data DateTime = DateTime { days:: Int,
sec :: Maybe Int,
ms :: Maybe Int,
ns :: Maybe Int
}
-- list all possibilities
data DateTime = DateOnly Int
| DateWithSec Int Int
| DateWithMilliSec Int Int Int
| DateWithNanoSec Int Int Int Int
-- cascaded Maybe
data DateTime = DateTime Int (Maybe (Int, Maybe (Int, Maybe Int)))
-- cascaded data
data Nano = NoNano | Nano Int
data MilliSec = NoMilliSec | MilliSec Int Nano
data Sec = NoSec | Sec Int MilliSec
data Date = Date Int Sec
que construyen usaría (por supuesto no se limita a los ejemplos anteriores), y por qué?
[intenciones]
estoy explorando las posibilidades de un tipo de fecha en Frege (http://code.google.com/p/frege/), utilizando date4j de DateTime
como una línea guía (como la fecha y la hora lib de Haskell es demasiado complicado, y java.util.Date
demasiado roto). En mi implementación actual de juguetes, todos los campos son obligatorios, pero, por supuesto, sería bueno liberar al usuario de la precisión no deseada (y la implementación original tiene campos opcionales).
Así que los principales objetivos son:
- seguridad: estados ilegales deben ser evitados a toda costa
- conveniencia: Debe ser fácil de trabajar con el tipo, por ejemplo, la coincidencia de patrones estaría bien, los cálculos del calendario debe ser fácil ...
No tan importantes son:
- rendimiento: Por supuesto trabajar con el tipo no debe ser demasiado lento, pero para la típica uso no tiene que sqeeze el último ciclo de reloj
- memoria: en los casos en que esto realmente importa, sería fácil derivar un formato de almacenamiento más compacto
- implementación concisa: Es una biblioteca, y estoy dispuesto a agregar todo el código necesario para que las cosas se suavicen
Dicho esto, todo esto es muy tentativo y no debe tomarse demasiado en serio.
No estoy seguro de que esto responda sin saber más acerca de sus requisitos. Puede depender de muchas cosas, incluidas las funciones que planea definir sobre el tipo, el rendimiento y las consideraciones de espacio (cantidad de indirecciones, oportunidades para desempaquetar campos, etc.) – hammar
Otra opción es usar un constructor simple 'DateTime = DateTime [Int ] 'que no se exporta de la biblioteca, y forzar toda interacción con el tipo a través de funciones como' mkDateTimeWithSec :: [Int] -> DateTime', 'isDateTimeWithSec :: DateTime -> Bool',' getSeconds :: DateTime -> Maybe Int', etc. No puede usar la coincidencia de patrones (pero puede que no sea terrible, ya que solo lo reemplaza con guardias y utiliza las funciones de acceso) pero explícitamente no permite a sus usuarios crear estados ilegales, ya que puede verificar todo en el momento de la construcción (por ejemplo, puede verificar valores negativos). –
La afirmación original de que los datos no especificados son opcionales en lugar de predeterminados lo convierte en un tipo muy artificial, las funciones de escritura para manipularlo serán tediosas. También puede tener como un valor basura con solo nanosegundos, pero nada segundos. Cambiaría la táctica y averiguaría si el incumplimiento de 0 para valores de tiempo no especificados es perjudicial en teoría y en práctica. –