Estoy tratando de traducir las Flechas de la biblioteca central de Haskell a F # (creo que es un buen ejercicio entender mejor las Flechas y F #, y podría usarlas en un proyecto en el que estoy trabajando). Sin embargo, la traducción directa no es posible debido a la diferencia en paradigmas. Haskell usa clases de tipos para expresar esto, pero no estoy seguro de qué construcciones F # asignen mejor la funcionalidad de las clases tipo con los modismos de F #. Tengo algunas ideas, pero pensé que sería mejor que apareciera aquí y ver lo que se consideraba lo más cercano a la funcionalidad.¿Cómo traduciría una clase de tipo Haskell a F #?
Para la multitud de tl; dr: ¿Cómo se traducen las clases de tipo (una expresión de Haskell) en el código idiomático de F #?
Para aquellos aceptar de mi larga explicación:
Este código de la lib estándar Haskell es un ejemplo de lo que estoy tratando de traducir:
class Category cat where
id :: cat a a
comp :: cat a b -> cat b c -> cat a c
class Category a => Arrow a where
arr :: (b -> c) -> a b c
first :: a b c -> a (b,d) (c,d)
instance Category (->) where
id f = f
instance Arrow (->) where
arr f = f
first f = f *** id
Intento 1: Módulos, tipos simples , que Vinculaciones
Mi primera oportunidad en esto era simplemente mapear cosas sobre el uso directo Módulos de organización, como:
type Arrow<'a,'b> = Arrow of ('a -> 'b)
let arr f = Arrow f
let first f = //some code that does the first op
Eso funciona, pero pierde polimorfismo, ya que no implemento Categorías y no pueda implementar fácilmente Flechas más especializadas.
Intento 1a: Refinación usando firmas y tipos
Una forma de corregir algunos problemas con el intento 1 es utilizar un archivo .fsi para definir los métodos (por lo que los tipos más fácil hacer cumplir) y utilizar algunas simples tipo ajustes para especializarse.
type ListArrow<'a,'b> = Arrow<['a],['b]>
//or
type ListArrow<'a,'b> = LA of Arrow<['a],['b]>
Pero el archivo FSI no se puede volver a utilizar (para hacer cumplir los tipos de las funciones obligado LET) para otras implementaciones, y el tipo de cambio de nombre/encapsular cosas es difícil.
Intento 2: Los modelos de objetos e interfaces
La racionalización que F # está diseñado para ser OO también, tal vez una jerarquía de tipos es la forma correcta de hacer esto.
type IArrow<'a,'b> =
abstract member comp : IArrow<'b,'c> -> IArrow<'a,'c>
type Arrow<'a,'b>(func:'a->'b) =
interface IArrow<'a,'b> with
member this.comp = //fun code involving "Arrow (fun x-> workOn x) :> IArrow"
Aparte de la cantidad de un dolor que puede ser conseguir lo que debería ser métodos estáticos (como un borrador y otros operadores) para actuar como métodos de instancia, también existe la necesidad de upcast explícitamente los resultados. Tampoco estoy seguro de que esta metodología todavía esté capturando la expresividad total del polimorfismo de tipo de clase. También hace que sea difícil usar cosas que DEBEN ser métodos estáticos.
Intento 2a: Refinación usando extensiones de tipos de
Así que un mayor refinamiento potencial es declarar las interfaces tan desnudas como sea posible, a continuación, utilizar los métodos de extensión para agregar funcionalidad a todo tipo de aplicación.
type IArrow<'a,'b> with
static member (&&&) f = //code to do the fanout operation
Ah, pero esto me encierra en el uso de un método para todos los tipos de IArrow.Si quisiera un poco diferente (& & &) para ListArrows, ¿qué puedo hacer? No he probado este método todavía, pero creo que puedo sombrear el (& & &), o al menos proporcionar una versión más especializada, pero creo que no puedo exigir el uso de la variante correcta.
Ayúdame
Entonces, ¿qué se supone que voy a hacer aquí? Siento que OO debería ser lo suficientemente potente como para reemplazar las clases de tipo, pero parece que no puedo encontrar la manera de hacerlo en F #. ¿Alguno de mis intentos estuvo cerca? ¿Alguno de ellos es "tan bueno como puede ser" y eso tendrá que ser lo suficientemente bueno?
"¿Cómo se traducen las clases de tipo (una expresión de Haskell) en el código idiomático F #?" Mala idea. Debería ver el * problema * que estaba tratando de resolver en lugar de la solución que pasó a usar las clases de tipo y descubrir cómo resolverlo utilizando la función que F # proporciona. –
@Jon Harrop Ese es el punto de la pregunta. Haskell resuelve docenas de problemas con Type Classes, y quería saber cuáles eran las alternativas de F # para resolver una * clase * de problemas similar.Además, el puerto Arrow no sirve para resolver ningún problema, solo es una actividad de "pensé que sería divertido aprender más sobre Arrows". – CodexArcanum
Entonces, creo que sería realmente valioso si pudieras explicar algunos de los problemas que resuelven las clases de tipos y preguntar a las personas cómo resolverían los mismos problemas en F #. –