为什么这个Functor实例不正确?

hdi*_*zle 3 haskell functional-programming

我写了这段代码:

newtype Pixel a = Pixel (a,a,a) deriving (Show)

instance Functor [Pixel Int] where
    fmap f [] = []
    fmap f [Pixel(a,b,c)] = [Pixel(f a, b, c)]
Run Code Online (Sandbox Code Playgroud)

我希望仿函数应用于Pixel类型中的第一个元素,但我不断收到此错误:

New.hs:17:18: error:
• Expecting one fewer arguments to ‘[Pixel Int]’
  Expected kind ‘* -> *’, but ‘[Pixel Int]’ has kind ‘*’
• In the first argument of ‘Functor’, namely ‘[Pixel Int]’
  In the instance declaration for ‘Functor [Pixel Int]’
Run Code Online (Sandbox Code Playgroud)

我在这个问题上很丢失,有没有办法在整个列表中应用仿函数?或者我是否需要为单个Pixel类型设置仿函数,然后遍历列表?

Aad*_*hah 5

根据我的理解,你会得到一个像素列表,你想要改变每个像素的第一个分量(即红色分量).因此,您需要以下功能:

changeAllPixels :: [Pixel Int] -> [Pixel Int]
Run Code Online (Sandbox Code Playgroud)

问:我们如何更改列表中的每个元素?答:我们使用map:

changeAllPixels = map changeOnePixel

changeOnePixel :: Pixel Int -> Pixel Int
Run Code Online (Sandbox Code Playgroud)

我们只想更改红色组件.因此,我们有:

changeOnePixel = changeRedComponent doSomething

changeRedComponent :: (a -> a) -> Pixel a -> Pixel a
changeRedComponent f (Pixel (r, g, b)) = Pixel (f r, g, b)

doSomething :: Int -> Int
Run Code Online (Sandbox Code Playgroud)

现在你只需要实现doSomething.例如,如果要反转红色组件,则可以doSomething按如下方式实现:

doSomething x = 255 - x
Run Code Online (Sandbox Code Playgroud)

请注意,我们没有制作Pixel实例Functor.这是因为我们只想更改红色组件并单独留下绿色和蓝色组件.然而map,我们使用的是fmap列表.

我认为你遇到的最大问题是你不能很好地理解仿函数.你可能应该花一些时间熟悉它们.