我有以下类型newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a }
。
我必须为它编写Functor实例,但我真的不明白如何
我试过了
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 (g a)
和
instance Functor (Arr2 e1 e2) where
fmap g = g . getArr2
实际上导致类型
(a -> b) -> Arr2 e1 e2 a -> b
而非期望的
(a -> b) -> Arr2 e1 e2 a -> Arr2 e1 e2 b
所以,请帮帮我
答案 0 :(得分:4)
Functor
类的定义如下:
class Functor f where:
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
(<$)
有一个默认实现:(<$) = fmap . const
可以正常工作。
这意味着如果我们输入一个函数(g :: a -> b
)作为第一个参数,而Arr2
生成一个a
,我们必须生成一个Arr2
如果已应用,则在箭头的结果上调用g
。
因此,fmap
的{{1}}定义为:
Arr2
或更优雅:
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 (\x y -> g (a x y))
或更优雅的版本 - 由@Alec评论:
instance Functor (Arr2 e1 e2) where
fmap g (Arr2 a) = Arr2 (\x -> g . (a x))
(您可以使用this tool将表达式转换为 pointfree
答案 1 :(得分:0)
Willem Van Onsem提供的答案非常好,我只想建议使用可以轻松为新类型创建Functor
个实例的语言扩展程序:DeriveFunctor
。
在模块的顶部,您可以添加:
{-# LANGUAGE DeriveFunctor #-}
然后您可以自动派生您的Functor
实例:
newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a } deriving Functor
以下是我如何在GHCi中找到此实例的fmap
类型:
λ > :set -XDeriveFunctor
λ > newtype Arr2 e1 e2 a = Arr2 { getArr2 :: e1 -> e2 -> a } deriving Functor
λ > :set -XTypeApplications
λ > :t fmap @(Arr2 _ _)
fmap @(Arr2 _ _) :: (a -> b) -> Arr2 t t1 a -> Arr2 t t1 b