haskell - ¿Dónde pertenecen las instancias de QuickCheck en un paquete cabal?
(2)
El problema se reduce a: ¿qué tan probable es que alguien que use su biblioteca quiera ejecutar las pruebas de QuickCheck usando su tipo NBT
?
Si es probable, y la instancia arbitraria es detallada (y por lo tanto no es probable que cambie para diferentes personas), probablemente sería mejor enviarlo con su paquete, especialmente si se va a asegurar de seguir actualizando el paquete ( en cuanto a usar una bandera o no, eso se reduce a un poco de preferencia personal). Sin embargo, si la instancia es relativamente simple (y por lo tanto es más probable que las personas quieran personalizarla), podría ser una idea simplemente proporcionar una instancia de muestra en la documentación.
Si el tipo es principalmente de naturaleza interna y no es probable que sea utilizado por otros que deseen ejecutar pruebas, entonces usar una bandera para activar condicionalmente QuickCheck es probablemente la mejor manera de evitar dependencias innecesarias (es decir, la serie de pruebas está ahí para puedes probar el paquete).
No soy un fan de tener paquetes de QuickCheck solo en general, aunque podría ser útil en algunas situaciones.
Tengo un paquete cabal que exporta un tipo NBT
que podría ser útil para otros desarrolladores. Me he tomado la molestia de definir una instancia Arbitrary
para mi tipo, y sería una pena no ofrecérsela a otros desarrolladores para probar su código que integra mi trabajo.
Sin embargo, quiero evitar situaciones en las que mi instancia pueda interferir. Quizás el otro desarrollador tenga una idea diferente de lo que debería ser Arbitrary
instancia Arbitrary
. Quizás la dependencia de mi paquete en una versión particular de QuickCheck pueda interferir o no ser deseada en las dependencias del proyecto del cliente.
Mis ideas, en ningún orden en particular, son:
- Deje la instancia
Arbitrary
junto a la definición del tipo y deje que los clientes se ocupen de seguir la instancia o anular el número de versión de QuickCheck. - Convierta la instancia
Arbitrary
una instancia huérfana en un módulo separado dentro del mismo paquete, por ejemplo,Data.NBT.Arbitrary
. La dependencia de QuickCheck para el paquete general permanece. - Ofrezca la instancia
Arbitrary
en un paquete totalmente separado, de modo que pueda ser listado como una dependencia de prueba separada para proyectos de clientes. - Incluya condicionalmente tanto la instancia
Arbitrary
como la dependencia QuickCheck en el paquete principal, pero solo si se establece una-ftest
como-ftest
.
He visto combinaciones de todos estos utilizados en otras bibliotecas, pero no he encontrado ningún consenso sobre cuál funciona mejor. Quiero intentar hacerlo bien antes de subirlo a Hackage.
Sobre la base de no mucha experiencia específica, pero un deseo general de robustez, el principio guía para las dependencias de paquetes tal vez debería ser
De cada uno según su capacidad; a cada uno según su necesidad.
Es bueno mantener las dependencias de un paquete al mínimo necesario para su funcionalidad esencial. Eso me sugiere la opción 3 o la opción 4. Por supuesto, es un dolor cortar el paquete tanto. Si las opciones son capaces de expresar la condicionalidad involucrada, entonces la opción 4 parece un enfoque sensato, basado en el uso efectivo del lenguaje para decir lo que quiere decir.
Sería realmente bueno si surgiera un consenso acerca de cuál es el interruptor que debemos pulsar para obtener el kit de prueba, así como la funcionalidad básica.
También está claro que hay espacio para el refinamiento aquí. Es sorprendente que Cabal funcione tan bien como lo hace, pero podría permitir nociones más sofisticadas de "paquete", tal vez a la manera del sistema de módulos SML. Traducir las dependencias en tipos de funciones, básicamente escribimos
simplePackage :: (Dependency1, .., Dependencyn) -> Deliverable
pero uno podría imaginar combinaciones más elaboradas de productos y funciones, como
fancyPackage :: BasicDependency -> (BasicDeliverable, HelpfulExtras -> Gravy)
Hasta entonces, elija la opción que refleje con mayor precisión el trato real. Y cuéntanos sobre eso, para que podamos construir ese consenso.