2011-07-14 22 views
16

Mientras lee el artículo "Data types a la carte" by Wouter Swierstra, tengo pegado a traducir el siguiente código de Haskell en Scala:parametrizado tipo de datos en Scala

data Expr f = In (f (Expr f)) 

Expr es el tipo de datos utilizado para la representación de expresiones aritméticas en la forma en que específica expresiones pueden escribirse de la siguiente manera:

data Val e = Val Int 
type IntExpr = Expr Val 

data Add e = Add e e 
type AddExpr = Expr Add 

Mi problema es en la implementación de f (que podría ser considerado como el firma del constructor) en Scala.

P.S. Definición de un co-producto de dos firmas, puede más adelante combinar tipos de datos, obtener una expresión de tipo Expr (Val :+: Add):

data (f :+: g) e = Inl (f e) | Inr (g e) 

addExample :: Expr (Val :+: Add) 
addExample = In (Inr (Add (In (Inl (Val 118))) (In (Inl (Val 1219))))) 
+0

* n.b. * - [tag: adt] se trata de "Herramientas de desarrollo Android", no de tipos de datos algebraicos, y de todos modos el acrónimo ADT aplicado a los tipos de datos generalmente significa * abstract *, not * algebraic *. –

+0

Hay dos problemas que obstaculizan la implementación de esto de manera directa: 1) Cuantificación universal. 2) Unificación de orden superior. – Apocalisp

Respuesta

6

Tal vez algo así como

case class Expr[f[_]] (in : f [Expr[f]]) 

Esto no es tan útil como en Haskell sin embargo. Suponga que define

case class Val[e] (v: Int) 

Entonces Val(3) tendrá un tipo de Val[Nothing], y no se puede utilizar con Expr.

scala> val e = Expr(Val(3))    
<console>:9: error: no type parameters for method apply: 
(in: f[Expr[f]])Expr[f] in object Expr exist so that it can be applied 
to arguments (Val[Nothing]) 
--- because --- 
argument expression's type is not compatible with formal parameter type; 
found : Val[Nothing] 
required: ?f[ Expr[?f] ] 
     val e = Expr(Val(3)) 

Todavía puede especificar el tipo de forma explícita

val e = Expr(Val(3):Val[Expr[Val]]) 

pero esto no es divertido. Por supuesto, puede definir una función del tipo correcto y usarla en lugar de Val.

Tenga en cuenta que todavía soy un nova de Scala y quizás haya un método más elegante.

2

De repente encontré este blogpost que proporciona algunas buenas explicaciones sobre la traducción de "Tipos de datos a la carta" en Scala. solución propuesta es el siguiente:

case class Val[E](i: Int) 
case class Add[E](left: E, right: E) 

case class Expr[F[X]](e: F[Expr[F]]) 

sealed trait Sum[F[X], G[X], E] 
case class Inl[F[X], G[X], E](l: F[E]) extends Sum[F,G,E] 
case class Inr[F[X], G[X], E](r: G[E]) extends Sum[F,G,E] 

trait Apply2Of3[F[A[_],B[_],_],A[_],B[_]] { 
     type It[C] = F[A,B,C] 
} 

type Tmp[X] = Apply2Of3[Sum,Val,Add]#It[X] 

val addExample: Expr[Tmp] = In[Tmp](Inr(Add(In[Tmp](Inl(Val(118))), In[Tmp](Inl(Val(1219)))))) 

Es mucho no tan dulce como la original (hecha en Haskell), pero bastante útil en el sentido de que 1) se demuestra que por lo general es posible poner en práctica la idea de Scala y 2) saca a relucir algunas debilidades de Scala en comparación con Haskell.

Cuestiones relacionadas