包含函数的数据类型的函子实例

Rav*_*ave 6 monads haskell monad-transformers

我有一个数据类型定义为

data Foo a = Foo a (a -> a)
Run Code Online (Sandbox Code Playgroud)

Foo数据构造函数有两个参数值和功能。我需要为此编写 Monad 和 Monad 转换实例。

我正在尝试实现函子实例,

instance Functor Foo where 
  fmap f (Foo x g) = Foo (f x) (g .(f x))
Run Code Online (Sandbox Code Playgroud)

但我有一个错误Couldn't match type ‘a’ with ‘b’

这是正确的,因为g只接受类型af x会转换a->b。所以接下来我重写为

instance Functor Foo where 
  fmap f (Foo x g) = Foo (f x) g
Run Code Online (Sandbox Code Playgroud)

我遇到了同样的错误“无法将类型 'a' 与 'b' 匹配”。

我也试过这个

instance Functor Foo where 
  fmap f (Foo x g) = Foo (f x) (f. g x)
Run Code Online (Sandbox Code Playgroud)

我得到Occurs check: cannot construct the infinite type: a ~ b -> a(g.x)

我被卡住了,我知道函数g只接受 typea并返回 type a。但fmap会将 type 转换a为 type b。我想我已经申请fmapg为好,这我无法做到。

如何编写上述数据类型的实例?

Wil*_*sem 7

让我们考虑类型,我们基本上需要将 a 转换Foo a为 a Foo b,这意味着我们需要找到给定一个函数a -> b,一个 type 元素a和一个type函数,一个typea -> a元素b和一个 type 函数b -> b

尤其是最后一个比较困难,因为我们只给定了一个 type 的函数a -> b,而不是一个 type 的函数b -> a,我们不能先将输入转换为 a a,然后通过原始函数进行处理,然后将其映射回 a b

制作满足类型的映射并非完全不可能,例如:

fmap1 f (Foo x g) = Foo (f x) (const (f x))
Run Code Online (Sandbox Code Playgroud)

或者:

fmap2 f (Foo x g) = Foo (f x) id
Run Code Online (Sandbox Code Playgroud)

但是存在和需要满足法律的问题:fmap1fmap2

fmap id = id
Run Code Online (Sandbox Code Playgroud)

换句话说,fmap id (Foo x g)需要等于Foo x g,现在如果我们使用idor const (f x),那么idf x并不总是等于g,至少不是 ifg是一个可以采用任何形式的函数。

如果您当然考虑Foo x g并且Foo x (id x)例如是等效的,这在某些情况下可能是合理的,正如@leftaroundabout 所说,那么您可以将其实现为函子实例。

  • @pedrofurla 这是不正确的,它可能是各种各样的事情。提供“a -> a”函数的调用者也可以决定“a”是什么。例如,他们可以选择“Integer”,然后“(+1)”是正确类型的有效函数。当您必须“提供”一个函数(并且其他人可以实例化该类型变量)时,“id”是“a -> a -> a”类型的唯一函数的逻辑适用。当你得到一个函数时就不会了(除非你实例化类型变量)。 (2认同)