猿问

如何在 Go 中模拟 `fmap`?

我想fmap在 Go 中进行模拟。一个简单的例子:


type S [A any] struct {

  contents A

}


type Functor [A any, B any] interface{

  fmap(f func(A)B) B

}


func (x S[A]) fmap (f func(A)B) S[B] {

  x.contents = f(x.contents)

  return x

}

这失败了:undefined: B关于interface实施。有没有通用的解决方法?


慕后森
浏览 83回答 2
2回答

慕运维8079593

Go 的泛型和方法的组合不像 Haskell 的类型类那样富有表现力;至少还没有。特别是,正如 kostix 在他的评论中指出的那样,Go 允许泛型类型具有方法,但是除了接收者之外,这些方法的参数不能使用参数化类型。(来源)由于 Go 方法不能引入新的类型参数,因此B在您的方法中访问的唯一方法是像您所做的那样在您的类型fmap声明中引入它。Functor但这没有意义,因为根据类别理论,函子采用一个类型参数,而不是两个。这个例子可能足以让您相信,在 Go 中使用泛型和方法来模拟 Haskell 类型类是徒劳的。不过,您可以做的一件事是 implement fmap,不是作为方法,而是作为顶级函数:package mainimport "fmt"type S[A any] struct {    contents A}func Fmap[A, B any](sa S[A], f func(A) B) S[B] {    return S[B]{contents: f(sa.contents)}}func main() {    ss := S[string]{"foo"}    f := func(s string) int { return len(s) }    fmt.Println(Fmap(ss, f)) // {3}}但仅仅因为你可以并不意味着你应该。总是问问自己,将一种方法从其他语言转移到 Go 是否感觉正确。

繁星点点滴滴

我要补充一点,您遇到的一些问题是您从错误的定义开始。提议中应该有一些直接的危险信号Functor——type Functor [A any, B any] interface{                  // ^ Functor should wrap a single type ⚠️  fmap(f func(A)B) B                // ^ should return Functor-wrapped B ⚠️}解决你上面的问题,这就是我们想写的 -type Functor[A any] interface{  fmap[B any](f func(A)B) Functor[B]}然而,Go 警告我们就您面临的问题向我们提供直接反馈 -interface method must have no type parametersundefined: B正如 @jub0bs 在链接的答案中指出的那样,方法可能不会采用额外的类型参数。
随时随地看视频慕课网APP

相关分类

Go
我要回答