Параметризованный тип данных в Scala - PullRequest
17 голосов
/ 14 июля 2011

Читая статью "Типы данных по меню" Wouter Swierstra , я застрял при переводе следующего кода на Haskell в Scala:

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

Exprэто тип данных, используемый для представления арифметических выражений таким образом, что конкретные выражения могут быть записаны следующим образом:

data Val e = Val Int
type IntExpr = Expr Val

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

Моя проблема заключается в реализации f (которую можно рассматривать как сигнатуру конструктора) в Scala.

PS Определив побочный продукт из двух сигнатур, вы можете позже объединить типы данных, получив выражение типа 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)))))

Ответы [ 2 ]

6 голосов
/ 14 июля 2011

Возможно, что-то вроде

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

Это не так полезно, как в Haskell.Предположим, вы определили

case class Val[e] (v: Int)

Тогда Val(3) будет иметь тип Val[Nothing], и вы не можете использовать его с 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))

Вы все еще можете явно указать тип

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

, но это не весело.Вы, конечно, можете определить функцию правильного типа и использовать ее вместо Val.

Обратите внимание, что я все еще новичок Scala и, возможно, есть более элегантный метод.

2 голосов
/ 15 июля 2011

Я неожиданно обнаружил этот блог-пост , в котором содержатся некоторые хорошие объяснения по переводу «Типы данных по меню» в Scala.Предлагаемое решение выглядит следующим образом:

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))))))

Это далеко не так приятно, как оригинальное (сделанное на Haskell), но весьма полезно в том смысле, что 1) оно демонстрирует, что в целом можно реализовать идеюв Scala, и 2) поднимает некоторые слабости Scala по сравнению с Haskell.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...