[英]Why is this Functor instance incorrect?
I've written this code: 我写了这段代码:
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)]
I want the functor to apply to the first element in the Pixel
type, but I keep getting this error: 我想将仿函数应用于
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]’
I'm pretty lost on this issue, is there any way to apply a functor on an entire list? 我在这个问题上很丢失,有没有办法在整个列表中应用仿函数? Or do I need to set up a functor for an individual
Pixel
type and then iterate through a list? 或者我是否需要为单个
Pixel
类型设置仿函数, 然后遍历列表?
From what I understand, you're given a list of pixels and you want to change the first component (ie the red component) of every pixel. 根据我的理解,你会得到一个像素列表,你想要改变每个像素的第一个分量(即红色分量)。 Hence, you want the following function:
因此,您需要以下功能:
changeAllPixels :: [Pixel Int] -> [Pixel Int]
Q: How do we change every element of a list? 问:我们如何更改列表中的每个元素? A: We use
map
: 答:我们使用
map
:
changeAllPixels = map changeOnePixel
changeOnePixel :: Pixel Int -> Pixel Int
We only want to change the red component. 我们只想更改红色组件。 Hence, we have:
因此,我们有:
changeOnePixel = changeRedComponent doSomething
changeRedComponent :: (a -> a) -> Pixel a -> Pixel a
changeRedComponent f (Pixel (r, g, b)) = Pixel (f r, g, b)
doSomething :: Int -> Int
Now you only need to implement doSomething
. 现在你只需要实现
doSomething
。 For example, if you want to invert the red component then you could implement doSomething
as follows: 例如,如果要反转红色组件,则可以按如下方式实现
doSomething
:
doSomething x = 255 - x
Note that we didn't make Pixel
an instance of Functor
. 请注意,我们没有让
Pixel
成为Functor
一个实例。 This is because we only want to change the red component and leave the green and blue components alone. 这是因为我们只想更改红色组件并单独留下绿色和蓝色组件。 We did however use
map
which is the fmap
for lists. 然而,我们使用
map
作为列表的fmap
。
I think the biggest problem you have is that you don't understand functors well. 我认为你遇到的最大问题是你不能很好地理解仿函数。 You should probably spend some time getting acquainted with them.
你可能应该花一些时间熟悉它们。
Actually, [Pixel Int]
already has an instance of Functor
because it is a list []
. 实际上,
[Pixel Int]
已经有一个Functor
实例,因为它是一个列表[]
。 The Functor
instance for list []
is defined in GHC base (it uses the definition of map
). list
[]
的Functor
实例在GHC base中定义(它使用map
的定义)。 Now you just need a function that can be applied to each element of that list. 现在您只需要一个可以应用于该列表的每个元素的函数。
fmap show [(Pixel 0 0 0),(Pixel 1 0 0), (Pixel 0 1 0)]
Functor
is generally defined for some container type. 通常为某些容器类型定义
Functor
。 It takes a function and applies it to the contents of the container. 它需要一个函数并将其应用于容器的内容。 Then when you call
fmap
on a container that has an instance of Functor
, the compiler will check that the function can be applied to the elements of that container. 然后,当您在具有
Functor
实例的容器上调用fmap
时,编译器将检查该函数是否可以应用于该容器的元素。
If you are still confused about Functors, I recommend this tutorial: Functors, Applicatives, And Monads In Pictures . 如果你仍然对Functors感到困惑,我推荐这个教程: Functors,Applicatives和Monads In Pictures 。
Your syntax is a bit off, fmap
applies a function to a data type and you tell it how. 你的语法有点偏,
fmap
将一个函数应用于数据类型,你告诉它如何。 To change values for a list of pixels you would need to map (fmap f) over the list. 要更改像素列表的值,您需要在列表上映射(fmap f)。 Give this implementation a try.
试试这个实现。
instance Functor Pixel where
fmap f (Pixel (a,b,c)) = Pixel (f a, b, c)
Edit this won't work because a,b,c need to be of the same type and functors allow functions of type a->b
. 编辑这将不起作用,因为a,b,c需要是相同的类型,而functor允许类型
a->b
函数。
As @AlexisKing commented you should use fmap
, but instead write a function like mapPixelFirst :: (a -> a) -> Pixel a -> Pixel a
. 正如@AlexisKing评论你应该使用
fmap
,而是写一个像mapPixelFirst :: (a -> a) -> Pixel a -> Pixel a
的函数。 Then map this function over user list, don't use fmap. 然后将此功能映射到用户列表,不要使用fmap。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.