雙函子有一個帶有這個簽名的映射函式:
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
你也可以有這樣的地圖:
othermap :: ((a, c) -> (b, d)) -> p a c -> p b d
具有此函式的型別是雙函子的嚴格子集(您始終可以定義bimapusingothermap但反之則不行)。第二個簽名有名字嗎?
追問:這個中間函式呢?
halfothermap :: ((a, c) -> b) -> (c -> d) -> p a c -> p b d
uj5u.com熱心網友回復:
作為 Bifunctor 的型別不需要與a值具有相同數量的b值。考慮,例如,
data TwoLists a b = TwoLists [a] [b]
這很容易實作bimap,但這othermap是一個真正的問題,尤其是當其中一個串列為空時。
othermap f (TwoLists [] (b:bs)) = TwoLists [] _
你能在這里做什么?您需要呼叫f以將所有的轉換bs為 type 的串列[d],但只有a在手頭有一個時才能呼叫該函式。
也許更糟糕的是一種根本沒有真正b價值的型別:
data TaggedFunction k a b = TaggedFunction a (k -> b)
instance Bifunctor (TaggedFunction k) where
bimap f g (TaggedFunction a b) = TaggedFunction (f a) (g . b)
你如何實作othermap這種型別?您可以更新該函式,因為您a手頭有一個b,并且在您需要一個d. 但是您無法a用 a替換c,因為您無法使用 ab來呼叫othermap的函式。
所以你不能把這個函式放在 Bifunctor 中。也許你會問,為什么不把它放在一個新的類中?我認為 leftroundabout 是正確的,因為這門課太拘束而無用。othermap只有當您的結構中具有相同數量的as 和bs時才能定義s ,即當您的結構是一些f包裹在型別 元組周圍的函子時(a, b)。例如,我們可以定義而不是 TwoLists
newtype PairList a b = PairList [(a, b)]
這可以有一個othermap定義。但這只是
othermap f (PairList vs) = PairList (fmap f vs)
同樣,我們可以定義而不是 TaggedFunction
newtype MultiFunction k a b = MultiFunction (k -> (a, b))
但othermap定義再次只是對 的包裝呼叫fmap:
othermap f (MultiFunction g) = MultiFunction (fmap f g)
因此,也許想象定義這種抽象的最好方法是,不是一個型別類函式,而是一個對捕獲這種組合的型別進行操作的普通函式:
newtype TupleFunctor f a b = TupleFunctor (f (a, b))
othermap :: Functor f => ((a, b) -> (c, d))
-> TupleFunctor f a b -> TupleFunctor f c d
othermap f (TupleFunctor x) = TupleFunctor (fmap f x)
uj5u.com熱心網友回復:
(擴展@glennsl 的評論...)
該型 p a c“包含”既a和c。
但是 type 的函式(a, c) -> (b, d)需要type和type 的值才能被呼叫,而 type 的值不一定同時具有。a cp a c
othermap @Either :: ((a, c) -> (b, d)) -> Either a c -> Either b d
othermap f (Left x) = ?
othermap f (Right y) = ?
無法othermap生成bor型別的值d,因為f在任何一種情況下它都無法呼叫。
第一個引數的型別意味著一個與 同構的雙函子(,),這并非所有可能的雙函子都成立。othermap事實上,比更具體bimap。(這里似乎有一個逆變關系,我不會試圖精確說明。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/398728.html
上一篇:寫入檔案的好習慣
