Entiendo por qué quiere hacer esto, pero desafortunadamente, puede ser solo una ilusión que las clases de Haskell parecen estar "abiertas" en la forma en que usted dice. Mucha gente siente que la posibilidad de hacer esto es un error en la especificación de Haskell, por las razones que explicaré a continuación. De todos modos, si realmente no es apropiado para la instancia, debe declararse en el módulo donde se declara la clase o en el módulo donde se declara el tipo, eso probablemente sea una señal de que debería estar usando una newtype
o alguna otra envoltura alrededor de su tipo.
Las razones por las que deben evitarse las instancias huérfanas son mucho más profundas que la conveniencia del compilador. Este tema es bastante controvertido, como puede ver en otras respuestas. Para equilibrar la discusión, voy a explicar el punto de vista de que uno nunca, nunca, debe escribir instancias huérfanas, que creo que es la opinión mayoritaria entre los Haskellers experimentados. Mi propia opinión está en algún punto intermedio, que explicaré al final.
El problema surge del hecho de que cuando existe más de una declaración de instancia para la misma clase y tipo, no hay ningún mecanismo en Haskell estándar para especificar cuál usar. Más bien, el programa es rechazado por el compilador.
El efecto más simple de eso es que podría tener un programa que funcione perfectamente y que de repente deje de compilarse debido a un cambio que alguien más hace en alguna dependencia lejana de su módulo.
Peor aún, es posible que un programa en funcionamiento comience a fallar en tiempo de ejecución debido a un cambio distante. Podría estar usando un método que asume que proviene de una determinada declaración de instancia, y podría ser reemplazado silenciosamente por una instancia diferente que sea lo suficientemente diferente como para hacer que su programa comience a fallar inexplicablemente.
Las personas que quieren garantías de que estos problemas nunca les sucederán deben seguir la regla de que si alguien, en cualquier lugar, alguna vez ha declarado una instancia de cierta clase para un cierto tipo, ninguna otra instancia debe volver a declararse en ningún programa escrito. Por cualquiera. Por supuesto, existe la solución de usar a newtype
para declarar una nueva instancia, pero eso siempre es al menos un inconveniente menor y, a veces, uno importante. Entonces, en este sentido, aquellos que escriben instancias huérfanas intencionalmente están siendo bastante descorteses.
Entonces, ¿qué se debe hacer con este problema? El campo anti-instancia huérfana dice que la advertencia de GHC es un error, debe ser un error que rechace cualquier intento de declarar una instancia huérfana. Mientras tanto, debemos ejercitar la autodisciplina y evitarlos a toda costa.
Como has visto, hay quienes no están tan preocupados por esos posibles problemas. De hecho, fomentan el uso de instancias huérfanas como una herramienta para la separación de preocupaciones, como usted sugiere, y dicen que uno debe asegurarse, caso por caso, de que no haya ningún problema. Las instancias huérfanas de otras personas me han molestado suficientes veces para convencerme de que esta actitud es demasiado arrogante.
Creo que la solución correcta sería agregar una extensión al mecanismo de importación de Haskell que controlaría la importación de instancias. Eso no resolvería los problemas por completo, pero ayudaría en cierta medida a proteger nuestros programas contra el daño de las instancias huérfanas que ya existen en el mundo. Y luego, con el tiempo, podría convencerme de que, en ciertos casos limitados, quizás una instancia huérfana no sea tan mala. (Y esa misma tentación es la razón por la que algunos en el campo anti-instancia huérfana se oponen a mi propuesta).
Mi conclusión de todo esto es que, al menos por el momento, le recomendaría encarecidamente que evite declarar cualquier instancia huérfana, para ser considerado con los demás si no es por otra razón. Utilice un newtype
.