gpt4 book ai didi

Scala 相当于 'forall a. Set a -> Set a -> Set a'

转载 作者:行者123 更新时间:2023-12-01 23:52:54 27 4
gpt4 key购买 nike

在 haskell 中我可以写一个函数 f where

f :: Set a -> Set a -> Set a

如果我采用 Set Int 类型的两组 s1s2,然后执行 f s1 s2 它将产生类型为 Set Int 的东西。

但是在 scala 中,我不能这样写,因为 A 是某种固定类型,与长。

val x = Set(3L)
val y = Set(4L)

def foo[A](f: (Set[A], Set [A]) => Set [A]) = {
f(x,y)
}

不过,我真正想要的是 def foo[forall A. A] ...。我怎么写这个?

编辑 动机是我从一个来源检索数据(x & y),以及调用方法他们来自另一个来源。 x & y 只是一些包含任何东西的集合,但已知是同一类型。
如果我有一些适当的多态函数,我可以只传递 x&y ,并且交集(或其他)可以正常工作,因为交集不关心集,只是他们被订购了。也许我已经忘记了如何以非 haskell 的方式做到这一点......

最佳答案

在 Scala 和 Haskell 中,f 的类型是相似的(直至同构):

f :: forall a. Set a -> Set a -> Set a
def f[A]: (Set[A], Set[A]) => Set[A]

Scala 中的泛型类型参数与 Haskell 中的类型变量的工作方式完全相同。所以我不确定你为什么说在 Scala 中这是不可能的——它不仅可能而且看起来非常相似。您可以使用任意集合作为参数调用 f,就像在 Haskell 中那样:

f[Int](Set(1, 2), Set(3, 4))

当您想将一个多态 函数传递给另一个可以使用任意类型的函数时,差异就开始了。在 Haskell 中,它需要更高级别的多态性:

foo :: (forall a. Set a -> Set a -> Set a) -> Whatever
foo f = toWhatever $ f (makeSet [1, 2, 3]) (makeSet [4, 5, 6]) // you get the idea

Scala 在其类型系统中没有与此直接对应的东西。您需要做一个特殊的技巧来编码类型之间所需的关系。首先,定义一个附加特征:

trait PolyFunction2[F[_], G[_], H[_]] {
def apply[A](f: F[A], g: G[A]): H[A]
}

然后你需要扩展这个特性来定义多态函数:

def f = new PolyFunction2[Set, Set, Set] {
def apply[A](f: Set[A], g: Set[A]): Set[A] = f ++ g
}

并且你需要使用这个特性来定义类型参数:

def foo(f: PolyFunction2[Set, Set, Set]): (Set[Int], Set[String]) =
(f(Set(1, 2), Set(3, 4)), f(Set("a"), Set("b")))

scala> foo(f)
res1: (Set[Int], Set[String]) = (Set(1, 2, 3, 4),Set(a, b))

当然,这是一个临时实现,因此您最好使用 Shapeless,因为它更通用。

关于Scala 相当于 'forall a. Set a -> Set a -> Set a',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25627035/

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