翻译/编码Haskell的数据Obj = forall a。 (显示a)=> Obj a`在斯卡拉 [英] Translate/encode Haskell's `data Obj = forall a. (Show a) => Obj a` in Scala

查看:125
本文介绍了翻译/编码Haskell的数据Obj = forall a。 (显示a)=> Obj a`在斯卡拉的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法想出如何在Scala中对 Obj 进行编码:

  { - #LANGUAGE ExistentialQuantification# - } 

data Obj = forall a。 (显示a)=> Obj a

实例Show Obj where show(Obj a)=Obj++ show a

main = print $ show [Objhello,Obj 3,Obj True]

运行时,上面的输出结果如下:

  [Objhello,Obj 3,Obj True] 

然而,在Scala中,这似乎并没有编译出来:

  forSome {type T;隐式val ev:显示[T]} 

b

  forSome {type T:Show [T]} 

这甚至可能在类型系统级别,或者我需要使用类似这样的方法捕获类型实例:

  class Obj [T](val x:T)(implicit val:Show [T])// ...或类似

任何见解都会被赞赏!

解决方案

  import scalaz._ 
import scalaz.Scalaz._

trait Obj {
type T //存在类型
val x:T
隐式val显示:显示[T]
}

隐式值objSow:显示[Obj] = Show.shows [Obj] {(x:Obj)=>
x.show.shows(xx)
}

object Obj {
/ *constructor* /
def apply [U](_ x :U)(隐式_show:显示[U]):Obj = new Obj {
type T = U
val x = _x
val show = _show
}
}

val test:List [Obj] = List(Obj(1),Obj(true),Obj(foo))

/ *
scala> test.shows
res0:String = [1,true,foo]
* /

PS我想在应用中使用 T show / code>;不是 U _show 。如果有人知道如何避免阴影,我会感激!






或者,您可以使用 forSome

  import scala.language.existentials 

trait ObjE {
val对:Tuple2 [T,Show [T]] forSome {type T}
}

/ *为了定义Show实例,我们必须帮助编译器统一`T`配对组件。 * /
def showDepPair [T] = Show.shows [Tuple2 [T,Show [T]]] {x => x._2.shows(x._1)}
implicit val showObjE = Show.shows [ObjE] {x =>我们必须使用 Tuple2 (或其他辅助类型)捕捉显示。我更喜欢上一个变体。对我来说,围绕一个类型成员来包装头脑更容易。



同样在 ScalaDon Giovanni forSome 语法将被取消,支持 val对:({typeλ[T] = Tuple2 [T,Show [T]]})#λ[_]} ,它已经可以工作了。我希望会有一些对类型的语法支持lambda 类型投影仪在这种情况下无助于(重复使用 Ť)。可能类似于 Typelevel scalac val pair:([T] => Tuple2 [T,Show [T])[_])

另一个基本变化是:

lockquote

一个基本概念–类型成员–可以给泛型,存在类型,通配符和更高级的类型提供确切的含义。

因此,这两种形式将等同于编译器的观点(在前者我们解开元组)。 我不是100%确定目前有什么区别,如果有的话



类型问题帮助我了解了scala当前的类型系统怪癖。


I've not been able to come up with how to encode Obj in Scala:

{-# LANGUAGE ExistentialQuantification #-}

data Obj = forall a. (Show a) => Obj a

instance Show Obj where show (Obj a) = "Obj " ++ show a

main = print $ show [Obj "hello", Obj 3, Obj True]

when run, the above produces the following output:

[Obj "hello",Obj 3,Obj True]

In Scala, however, this does not seem to compile:

forSome { type T; implicit val ev: Show[T] }

and neither does this:

forSome { type T : Show[T] }

Is this even possible at the type system level, or do I need to "capture" the type class instance using something like this:

class Obj[T](val x: T)(implicit val: Show[T])  // ...or similar

Any insight would be appreciated!

解决方案

You got it almost right:

import scalaz._
import scalaz.Scalaz._

trait Obj {
  type T // existential type
  val x: T
  implicit val show: Show[T]
}

implicit val objSow: Show[Obj] = Show.shows[Obj] { (x: Obj) =>
  x.show.shows(x.x)
}

object Obj {
  /* "constructor" */
  def apply[U](_x: U)(implicit _show: Show[U]): Obj = new Obj {
    type T = U
    val x = _x
    val show = _show
  }
}

val test: List[Obj] = List(Obj(1), Obj(true), Obj("foo"))

/*
scala> test.shows
res0: String = [1,true,"foo"]
*/

P.S I'd like to use T and show in apply; not U and _show. If someone knows how to avoid shadowing, I'll appreciate!


Alternatively you could use forSome:

import scala.language.existentials

trait ObjE {
  val pair: Tuple2[T, Show[T]] forSome { type T }
}

/* And to define Show instance we have to help compiler unify `T` in pair components. */
def showDepPair[T] = Show.shows[Tuple2[T, Show[T]]] { x => x._2.shows(x._1) }
implicit val showObjE = Show.shows[ObjE] { x => showDepPair.shows(x.pair) }

Here we have to use Tuple2 (or other auxillary type) to capture Show. I like the previous variant more. For me it's easier to wrap a mind around a type member.

Also in Scala "Don Giovanni" forSome syntax will be eliminated in favour of val pair: ({ type λ[T] = Tuple2[T, Show[T]] })#λ[_] }, which works already too. I hope there will be some syntax support for type lambdas as well. kind-projector doesn't help in this situation (repeated use of T). Maybe something like in Typelevel scalac: val pair: ([T] => Tuple2[T, Show[T])[_]).

Another foundational change will be:

A single fundamental concept – type members – can give a precise meaning to generics, existential types, wildcards, and higher-kinded types.

So the both forms will be equivalent from the point of view of the compiler (in former we unpack the tuple). I'm not 100% sure what are the differences currently, if there are any.

P.S. The Troubles with Types helped me understand scala's current type system quirks.

这篇关于翻译/编码Haskell的数据Obj = forall a。 (显示a)=> Obj a`在斯卡拉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆