gpt4 book ai didi

scala - 如何将 Haskell 翻译成 Scalaz?

转载 作者:行者123 更新时间:2023-12-04 10:42:12 25 4
gpt4 key购买 nike

我和我的一个高中生将尝试将 Haskell 的 Parsec 解析器组合库移植到 Scala 中。 (与 Scala 的内置解析库相比,它的优势在于您可以相当轻松地传递状态,因为所有解析器都是单子(monad)。)

我遇到的第一个障碍是试图弄清楚 Functor 在 scalaz 中是如何工作的。有人可以解释如何转换这个 Haskell 代码:

data Reply s u a = Ok a !(State s u) ParseError
| Error ParseError


instance Functor (Reply s u) where
fmap f (Ok x s e) = Ok (f x) s e
fmap _ (Error e) = Error e -- XXX

进入 Scala(我假设使用 Scalaz)。我做到了
sealed abstract class Reply[S, U, A]
case class Ok[S, U, A](a: A, state: State[S, U], error: ParseError)
extends Reply[S, U, A]
case class Error[S, U, A](error: ParseError) extends Reply[S, U, A]

知道我应该做 Reply扩展 scalaz.Functor特质,但我无法弄清楚如何做到这一点。 (大多数情况下,我无法弄清楚 F[_] 参数的作用。)

任何帮助表示赞赏!

谢谢,
托德

根据 dflemstr 的回答,我想出了这个:
sealed abstract class Reply[S, U, A]
object Reply {
implicit def ReplyFunctor[S, U] = {
type ReplySU[A] = Reply[S, U, A]
new Functor[ReplySU] {
def fmap[A, B](r: ReplySU[A], f: A => B) = r match {
case Ok(a, state, error) => Ok(f(a), state, error)
case Error(error) => Error[S, U, B](error)
}
}
}
}
case class Ok[S, U, A](a: A, state: State[S, U], error: ParseError)
extends Reply[S, U, A]()
case class Error[S, U, A](error: ParseError) extends Reply[S, U, A]()

我不确定的是 ReplySU[A]类型。实际 Functor在 Haskell 中是 Reply s u带有 curry 类型和 a类型缺失。这是我应该如何在 Scala 中做同样的事情,还是我过于复杂了?

最佳答案

Functor[F[_]] , F意味着它是一个类型构造函数,也就是一个参数化类型,它必须以某种其他类型作为参数才能成为完全限定类型。例如,如果 FList ,然后 List[Int]是该参数化类型的类型实例。

因此,当您定义 Functor[List] 类型的值时, 这意味着它是描述 List 的仿函数性质的对象s,并且仿函数对象将使用高阶类型List构造各种类型的实例,例如 List[A]List[B] .

此外,您必须了解 Scala 的类和 Haskell 的类之间的区别。 Haskell 中的类实例最好由 Scala 中的隐式值建模,而不是接口(interface)的实现;虽然在 Java/Scala 中您需要一个对象的实例来拥有一个接口(interface)的实例,但您可以在 Haskell 中拥有一个类的实例,而无需该类处理的值类型的实例。

例如,想象一下您将如何实现 Read Scala 中的 Haskell 类。 Read类反序列化字符串中的值;有一个函数叫做 read类型为 Read a => String -> a所以对于任何类型a其中有一个 Read例如,您可以转换 String进入 a 类型的实例.如果您使用 Scala 中的接口(interface)对其建模,例如 class Foo implements Read[Foo] ,然后如何将字符串转换为 Foo 的实例? ?您不能调用Foo.read因为你没有 Foo然而; read函数应该返回一个!

相反,您创建一个单独的 ReadFoo: Read[Foo]包含 Read 函数实现的对象对于类型 Foo .然后您可以调用ReadFoo.read(string: String): Foo并获得 Foo返回类型安全。

对于仿函数实例,您需要以下内容:

// All implicits in the companion object of Reply are automatically brought into
// scope when Reply is imported
object Reply {
// Describes how to treat a `Reply` as a functor
implicit val ReplyFunctor: Functor[Reply] = new Functor[Reply] {
def fmap[A, B](r: Reply[A], f: A => B) = r match {
case Ok(x, s, e) => Ok(f(x), s, e)
case err => err // leave value unchanged
}
}
}

关于scala - 如何将 Haskell 翻译成 Scalaz?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9941199/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com