2014-11-23 49 views
0

我有我的類型構造的方式,我相信這將遵循函數法則,其中規定應該有一個身份函數fmap返回原函子。爲什麼我不能在一個實例Functor(( - >)ConcreteType)中創建一個(Functor f)=> ConcreteType - > f String?

代碼:

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

回答

6

你已經過分專注。

函子的定義如下:

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

的想法是,它需要一個正常的功能,它提高到一定範圍內。但不止於此:這個想法是需要的任何正常的功能,並將其引入到上下文中。對於列表函子,fmap可以使用任何函數並通過適當類型的列表執行它。

你所做的總是從你的函子返回相同的類型,這破壞了它作爲函子的目的,因此Haskell不允許。

1

考慮的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

+0

好點 - 我認爲我有類型的工作,但我想這是上午1點編碼對你做的。我回去試圖找出符合fmap的類型,但不能這樣做。 – josiah 2014-11-23 17:57:24

相關問題