2012-05-30 51 views
5

我在尋找函數,應用函子...我不知道如何到達我想要的位置,但我有這樣的感覺,應該讓我更接近。我可以繪製一對沒有箭頭的第一個元素嗎?

有一個簡單的方法,使map -alike只適用於2元組的第一個元素?從Control.Arrowfirst和使用Arrow (->),該做的伎倆很好:

map . first :: (b -> c) -> [(b, d)] -> [(c, d)] 

我唯一擔心的是,我還沒有獲得對箭真正的直覺,所以我可能會發現自己在深水早晚以後如果我保持這種狀態。另外,這似乎是一個相當方便的情況,不能一概而論。

我可以通過使用函子,單子什麼的獲得相同的功能其他任何,同時獲得到我想要的心臟?我正在玩弄

\f -> map (f `on` fst) 

-like想法,但不能完全達到那裏。

+11

如果使用的是抽象的,你不明白讓你感到不舒服,使用抽象版本較低的地圖(\(a,b) - >(fa,b))'完全沒有任何問題。 –

+0

感謝您的所有建議!這真的很有啓發。已經接受了您最高票數的答案。 – Ashe

+0

檢查http://stackoverflow.com/questions/413930如果你覺得不舒服'地圖。 first'。 – sdcvvc

回答

9

箭頭有對元組操作好的組合程序。你幾乎可以認爲它們是缺失的元組函數!

因此,例如,

> :t \f -> map (f *** id) 
    :: (b -> c) -> [(b, c')] -> [(c, c')] 

是映射第一個組件的有用方法。

+2

也可以使用(從Control.Arrow)「map(first f)」將一個函數應用於一對的第一個元素,同樣使用「map(second f)」將其應用於第二個元素。 – ozataman

5

,可以做這種事情的另一種抽象概念,是對bifunctor。 Edward Kmett有一個叫bifunctors的包。 Data.Bifunctor有一個類型的類正是這個功能,它包括2元組的例子。

1

嗯,還有就是BiFunctor包。

或者你可以使用反向對類型:

data Flip a b = Flip b a 

instance Functor (Flip a) where 
    fmap f (Flip x y) = Flip (f x) y 
2

所以你要找(a -> b) -> (a,c) -> (b,c)類型的函數。如果你只寫

{-# LANGUAGE TupleSections #-} 
instance Functor (,c) where 
    fmap f (x,c) = (f x, c) 

但是不幸的是,元組部分只能在值級別上工作。我不知道這是否有理論上的原因。我想它會擾亂高階統一。

Hayoo想出了包Data.Tuple.HT在函數被調用mapFst

沒有上升到bifunctors((,)的BiFunctor實例真的只做你想要的,沒有更多)或箭頭,沒有辦法得到你想要的東西,至少我知道。

2

我認爲問題是,有太多的方法 - 我想我會與丹尼爾·瓦格納的建議去 - 但這裏的另一個用於娛樂:

{-#LANGUAGE DeriveFunctor, MultiParamTypeClasses #-} 
import Control.Newtype 

newtype P a b = P {p:: (b, a)} deriving (Show,Eq,Ord,Functor) 
instance Newtype (P a b) (b,a) where pack = P; unpack = p 

-- *Main> fmap even ("Hi",4) 
-- ("Hi",True) 
-- *Main> map (fmap even) [("Hi",4),("Bye",5)] 
-- [("Hi",True),("Bye",False)] 
-- *Main> under P (fmap even) (4,"Hi") 
-- (True,"Hi") 
-- *Main> map (under P (fmap even)) [(4,"Hi"),(5,"Bye")] 
-- [(True,"Hi"),(False,"Bye")] 
相關問題