Scala中的Haskell“forall”翻译
Posted
技术标签:
【中文标题】Scala中的Haskell“forall”翻译【英文标题】:Haskell "forall" translation in Scala 【发布时间】:2018-11-18 17:46:36 【问题描述】:我正在尝试将(非常有趣的)论文Build systems a la carte 中的代码从 Haskell 翻译成 Scala,以供自学。 我远不是 Scala 或 Haskell 方面的专家,因此在尝试编写(第 7 页)的等价物时遇到了困难:
newtype Task c k v = Task run :: forall f. c f => (k -> f v) -> f v
type Tasks c k v = k -> Maybe (Task c k v)
看了forall in Scala的帖子,我做了一个尝试,翻译一下forall指定的类型约束:
import scalaz.Applicative
import scala.language.higherKinds
trait MyApplicative[_]
trait SuchThat[F[_], G[_]]
def apply[A:G]: F[A]
trait Task[C[_], K, V]
type F[X] = (type f[_])#f SuchThat C
var runInt: (K => F[V]) => F[V] = null
def run = runInt
def apply(r: (K => F[V]) => F[V] ) =
runInt = r
class ApplicativeTask[K, V] extends Task[Applicative, K, V]
class MyTask[K,V] extends Task[MyApplicative, K, V]
object TasksObj
type Tasks[C[_], K, V] = K => Option[Task[C, K, V]]
但我收到此错误消息:
Error: kinds of the type arguments (scalaz.Applicative,K,V) do not conform to the expected kinds of the type parameters (type C,type K,type V) in trait Task.
scalaz.Applicative's type parameters do not match type C's expected parameters:
type F has one type parameter, but type _ has none
class ApplicativeTask[K, V] extends Task[Applicative, K, V]
相反,MyTask 类没有错误。我想这是因为 Scalaz Applicative 将类型构造函数作为参数(据我所知),而 MyApplicative 是一个简单类型。
我迷失在错综复杂的 Scala 类型系统中,如果有人能帮助我找到解决方案,我将不胜感激。
提前致谢。
【问题讨论】:
【参考方案1】:我们从 Haskell 代码开始。
newtype Task c k v = Task run :: forall f. c f => (k -> f v) -> f v
在Scala中,我们必须显式注释类型参数的种类,所以我们向ghci
询问构造函数Task
的类型:
> :t Task
Task :: (forall (f :: * -> *). c f => (k -> f v) -> f v) -> Task c k v
我们知道f
有一种* -> *
,所以我们必须在Scala 中使用F[_]
来指定它。
然后我们向ghci
询问Task
的类型:
> :k Task
Task :: ((* -> *) -> Constraint) -> * -> * -> *
我们了解到k
和v
都具有善意*
,而c
拥有善意((* -> *) -> Constraint)
。在 Scala 中,我们不需要为 kind *
做任何特别的事情,但对于 ((* -> *) -> Constraint
,我们必须做两件事:
*
而不是 Constraint
,因为约束在 Scala 中被编码为正确的类型
我们必须通过在 Scala 中使用 C[_[_]]
来指定结果类型 ((* -> *) -> *)
。
总的来说,我们得到:
trait Task[C[_[_]], K, V]
def run[F[_]: C](f: K => F[V]): F[V]
【讨论】:
感谢@Toxaris,您的回答非常明确且很有帮助。【参考方案2】:问题在于 Applicative 是一个类型类,它将更高种类的类型作为参数Applicative[F[_]]
。并且任务类需要C[_]
。
【讨论】:
以上是关于Scala中的Haskell“forall”翻译的主要内容,如果未能解决你的问题,请参考以下文章
在scala中使用forall()从Option [String]中提取字符串[重复]
Algebraic Data Type 及其在 Haskell 和 Scala 中的表现