为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Go 中模拟 `fmap`?

如何在 Go 中模拟 `fmap`?

Go
慕后森 2022-12-19 11:55:38
我想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实施。有没有通用的解决方法?
查看完整描述

2 回答

?
慕运维8079593

TA贡献1876条经验 获得超5个赞

Go 的泛型和方法的组合不像 Haskell 的类型类那样富有表现力;至少还没有。特别是,正如 kostix 在他的评论中指出的那样,

Go 允许泛型类型具有方法,但是除了接收者之外,这些方法的参数不能使用参数化类型。

来源

由于 Go 方法不能引入新的类型参数,因此B在您的方法中访问的唯一方法是像您所做的那样在您的类型fmap声明中引入它。Functor但这没有意义,因为根据类别理论,函子采用一个类型参数,而不是两个。

这个例子可能足以让您相信,在 Go 中使用泛型和方法来模拟 Haskell 类型类是徒劳的。


不过,您可以做的一件事是 implement fmap,不是作为方法,而是作为顶级函数:

package main


import "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 是否感觉正确。



查看完整回答
反对 回复 2022-12-19
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

我要补充一点,您遇到的一些问题是您从错误的定义开始。提议中应该有一些直接的危险信号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 parameters

undefined: B

正如 @jub0bs 在链接的答案中指出的那样,方法可能不会采用额外的类型参数



查看完整回答
反对 回复 2022-12-19
  • 2 回答
  • 0 关注
  • 82 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信