函子的实例

Ati*_*tin 5 haskell functor

我有以下类型newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a }。我必须为它编写 Functor 实例,但我真的不明白我是如何尝试的

instance Functor (Arr2 e1 e2) where
  fmap g (Arr2 a) = Arr2 (g a)
Run Code Online (Sandbox Code Playgroud)

instance Functor (Arr2 e1 e2) where
  fmap g = g . getArr2
Run Code Online (Sandbox Code Playgroud)

这实际上导致类型

(a -> b) -> Arr2 e1 e2 a -> b
Run Code Online (Sandbox Code Playgroud)

而不是想要

(a -> b) -> Arr2 e1 e2 a -> Arr2 e1 e2 b
Run Code Online (Sandbox Code Playgroud)

所以请帮帮我

Wil*_*sem 5

Functor班有作为的定义:

class Functor f where:
    fmap :: (a -> b) -> f a -> f b
    (<$) :: a -> f b -> f a
Run Code Online (Sandbox Code Playgroud)

(<$)有一个默认的实现:(<$) = fmap . const它工作正常。

所以这意味着,如果我们输入一个函数 ( g :: a -> b) 作为第一个参数,并且一个Arr2产生 an a,我们必须生成一个Arr2,如果它被应用,我们必须在箭头g结果上调用它。

因此fmap,您的定义Arr2是:

instance Functor (Arr2 e1 e2) where
  fmap g (Arr2 a) = Arr2 (\x y -> g (a x y))
Run Code Online (Sandbox Code Playgroud)

或者更优雅:

instance Functor (Arr2 e1 e2) where
  fmap g (Arr2 a) = Arr2 (\x -> g . (a x))
Run Code Online (Sandbox Code Playgroud)

或者更优雅的版本- @Alec评论:

instance Functor (Arr2 e1 e2) where
  fmap g (Arr2 a) = Arr2 ((g .) . a)
Run Code Online (Sandbox Code Playgroud)

(你可以转换表达式pointfree使用那些该工具

  • 如果你想变得更加&lt;s&gt;不可读&lt;/s&gt; 优雅,你可以做`fmap g (Arr2 a) = Arr2 ((g .) . a)`。 (2认同)
  • 当 pointfree 超越单个参数时,我喜欢使用 [SECs](http://conal.net/blog/posts/semantic-editor-combinator)。这个`(.)`部分的废话从来没有吸引过我 (2认同)