繁体   English   中英

为什么不能将(Functor f)=> ConcreteType-> f String制成实例Functor((->)ConcreteType)?

[英]Why can I not make a (Functor f) => ConcreteType -> f String into an instance Functor ((->) ConcreteType)?

我构造类型的方式,我相信这将遵循Functor法则,该法则规定应该有一个恒等函数,fmap为其返回原始函子。

码:

-- 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))

错误信息:

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

您太专业了。

函子的定义如下:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

这个想法是,它需要一个正常的功能,并将其提升到某种上下文中。 但这还不止于此:想法是它可以接受任何正常功能并将其提升到上下文中。 对于列表函子, fmap可以执行任何功能并在适当类型的列表上执行它。

您所做的总是总是从函子中返回相同的类型,这违反了将其用作函子的目的,因此Haskell不允许这样做。

考虑一下Functor的定义:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

该类或方法不限制类型ab ,因此您定义的任何fmap必须适用于任何类型ab 您可以定义自己的类型类,例如:

class MyFunctor f where
    myfmap :: (String -> String) -> f String -> f String

但是那不是Functor

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM