加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何将Haskell翻译成Scalaz?

发布时间:2020-12-16 19:16:43 所属栏目:安全 来源:网络整理
导读:我的一个高中生和我将尝试将一个 Haskell的Parsec解析器组合库移植到 Scala中. (它比 Scala的内置解析库更有优势,你可以相当容易地传递状态,因为所有的解析器都是monad.) 我遇到的第一个故障是试图弄清楚Functor在scalaz中的工作原理.有人可以解释如何转换此
我的一个高中生和我将尝试将一个 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,A](a: A,state: State[S,U],error: ParseError)
    extends Reply[S,A]
case class Error[S,A](error: ParseError) extends Reply[S,A]

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

任何帮助赞赏!

谢谢,
托德

根据dflemstr的回答,我想出了这个:

sealed abstract class Reply[S,A]
object Reply {
  implicit def ReplyFunctor[S,U]  = {
    type ReplySU[A] = Reply[S,A]
    new Functor[ReplySU] {
      def fmap[A,B](r: ReplySU[A],f: A => B) = r match {
        case Ok(a,state,error) => Ok(f(a),error)
        case Error(error) => Error[S,B](error)
      }
    }
  }
}
case class Ok[S,error: ParseError) 
    extends Reply[S,A]()
case class Error[S,A]()

我不确定的是ReplySU [A]类型. Haskell中的实际Functor是使用curried类型回复s和缺少的类型.这是我在Scala中应该做同样的事情还是我过于复杂的事情?

解决方法

在Functor [F [_]]中,F表示它是一个类型构造函数,即参数化类型,必须将其他类型作为参数才能成为完全限定类型.例如,如果F是List,则List [Int]是该参数化类型的类型实例.

因此,当您定义Functor [List]类型的值时,它意味着它是一个描述Lists函子性质的对象,并且functor对象将使用高阶类型List来构造各种类型实例,例如List [ A]和列表[B].

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

例如,想象一下如何从Scala中的Haskell实现Read类. Read类从字符串反序列化值;有一个名为read的函数,类型为Read a =>字符串 – >对于具有Read实例的任何类型,您可以将String转换为类型a的实例.如果您使用Scala中的接口对其进行建模,那么类Foo实现Read [Foo],那么您如何将字符串转换为Foo的实例?你不能打电话给Foo.read,因为你还没有Foo; read函数应该返回一个!

相反,您创建一个单独的ReadFoo:Read [Foo]对象,其中包含类型为Foo的Read函数的实现.然后你可以调用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),e)
      case err         => err // leave value unchanged
    }
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读