[英]Why can I not make a (Functor f) => ConcreteType -> f String into an instance Functor ((->) ConcreteType)?
The way I have my types constructed, I believe this would follow the Functor law which states that there should be an identity function for which fmap returns the original functor. 我构造类型的方式,我相信这将遵循Functor法则,该法则规定应该有一个恒等函数,fmap为其返回原始函子。
Code: 码:
-- apply a style function to a shell prompt functor
-- e.g.
-- bold & fgColor red `style` gitCurrentBranch
style :: (String -> ShellPromptType -> String) -> ShellPromptSegment String
-> ShellPromptType -> ShellPromptSegment String
style f segment = \shType -> (flip f) shType <$> segment
-- this is fine
style' :: (String -> ShellPromptType -> String)
-> (ShellPromptType -> ShellPromptSegment String)
-> ShellPromptType -> ShellPromptSegment String
style' f makeSegment = flip f >>= \g shellType -> fmap g $ makeSegment shellType
-- this apparently is not. Compiler complains that it wants the type (String -> String) -> ShellPromptType -> b
-- for my lambda function there, but it gets (String -> String) -> ShellPromptType -> ShellPromptSegment String
-- instead. I guess 'b' is not allowed to be a functor?
instance Functor ((->) ShellPromptType) where
fmap f makeSegment = ((flip f) :: ShellPromptType -> String -> String)
>>= ((\g shellType -> fmap g $ makeSegment shellType)
:: (String -> String) -> ShellPromptType -> (ShellPromptSegment String))
Error message: 错误信息:
LambdaLine/Shells/ShellPromptSegment.hs|81 col 30 error| Couldn't match type `ShellPromptType -> String'
|| with `ShellPromptSegment String'
|| Expected type: (String -> String) -> ShellPromptType -> b
|| Actual type: (String -> String)
|| -> ShellPromptType -> ShellPromptSegment String
|| In the second argument of `(>>=)', namely
|| `((\ g shellType -> fmap g $ makeSegment shellType) ::
|| (String -> String)
|| -> ShellPromptType -> (ShellPromptSegment String))'
|| In the expression:
|| ((flip f) :: ShellPromptType -> String -> String)
|| >>=
|| ((\ g shellType -> fmap g $ makeSegment shellType) ::
|| (String -> String)
|| -> ShellPromptType -> (ShellPromptSegment String))
|| In an equation for `fmap':
|| fmap f makeSegment
|| = ((flip f) :: ShellPromptType -> String -> String)
|| >>=
|| ((\ g shellType -> fmap g $ makeSegment shellType) ::
|| (String -> String)
|| -> ShellPromptType -> (ShellPromptSegment String))
LambdaLine/Shells/ShellPromptSegment.hs|81 col 56 error| Couldn't match type `[Char]' with `ShellPromptSegment String'
|| Expected type: ShellPromptSegment String
|| Actual type: a
|| In the return type of a call of `makeSegment'
|| In the second argument of `($)', namely `makeSegment shellType'
|| In the expression: fmap g $ makeSegment shellType
You've overspecialized. 您太专业了。
The definition of a functor is as follows: 函子的定义如下:
class Functor f where
fmap :: (a -> b) -> f a -> f b
The idea is that it takes a normal function and raises it into some context. 这个想法是,它需要一个正常的功能,并将其提升到某种上下文中。 But it's more than that: the idea is that it takes any normal function and raises it into the context.
但这还不止于此:想法是它可以接受任何正常功能并将其提升到上下文中。 For the list functor,
fmap
can take any function and perform it over a list of the appropriate types. 对于列表函子,
fmap
可以执行任何功能并在适当类型的列表上执行它。
What you've done is always return the same type out of your functor, which defeats the purpose of it being a functor and thus is not allowed by Haskell. 您所做的总是总是从函子中返回相同的类型,这违反了将其用作函子的目的,因此Haskell不允许这样做。
Consider the definition of Functor
: 考虑一下
Functor
的定义:
class Functor f where
fmap :: (a -> b) -> f a -> f b
The class or the method doesn't constrain the types a
and b
, so any fmap
you define must be applicable to any types a
and b
. 该类或方法不限制类型
a
和b
,因此您定义的任何fmap
必须适用于任何类型a
和b
。 You could define your own type class, eg: 您可以定义自己的类型类,例如:
class MyFunctor f where
myfmap :: (String -> String) -> f String -> f String
but that wouldn't be Functor
. 但是那不是
Functor
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.