rlm*_*lms 6 haskell types functional-programming functor bifunctor
双函数有一个具有以下签名的映射函数:
bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
Run Code Online (Sandbox Code Playgroud)
你也可以有这样的地图:
othermap :: ((a, c) -> (b, d)) -> p a c -> p b d
Run Code Online (Sandbox Code Playgroud)
具有此函数的类型是双函子的严格子集(您始终可以定义bimapusing othermap,但反之则不然)。第二个签名有名字吗?
追问:这个中间函数呢?
halfothermap :: ((a, c) -> b) -> (c -> d) -> p a c -> p b d
Run Code Online (Sandbox Code Playgroud)
作为 Bifunctor 的类型不需要具有a与值相同数量的值b。例如,考虑一下,
data TwoLists a b = TwoLists [a] [b]
Run Code Online (Sandbox Code Playgroud)
它很容易实现bimap,但却othermap是一个真正的问题,特别是当其中一个列表为空时。
othermap f (TwoLists [] (b:bs)) = TwoLists [] _
Run Code Online (Sandbox Code Playgroud)
你在这里能做什么?您需要调用f将所有的转换bs为类型的列表,但只有在手头[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)
Run Code Online (Sandbox Code Playgroud)
如何实现othermap这种类型?您可以更新该功能,因为您a手头有一个,并且b在您需要时也会有一个d。但是您无法将 a 替换a为 a c,因为您无法获取 ab来调用othermap的函数。
所以你不能把这个函数放在Bifunctor中。也许你会问,为什么不把它放到一个新的类中呢?我认为 leftroundabout 是正确的,即该类过于受限而无用。仅当您的结构中othermap具有相同数量的as 和s 时,即当您的结构是包裹在类型 的元组周围的某个函子时,才可以定义。例如,我们可以定义而不是 TwoListsbf(a, b)
newtype PairList a b = PairList [(a, b)]
Run Code Online (Sandbox Code Playgroud)
这可以有一个othermap定义。但这只是
othermap f (PairList vs) = PairList (fmap f vs)
Run Code Online (Sandbox Code Playgroud)
同样,我们可以定义而不是 TaggedFunction
newtype MultiFunction k a b = MultiFunction (k -> (a, b))
Run Code Online (Sandbox Code Playgroud)
但othermap定义又只是对以下内容的包装调用fmap:
othermap f (MultiFunction g) = MultiFunction (fmap f g)
Run Code Online (Sandbox Code Playgroud)
因此,想象定义此抽象的最佳方式可能不是类型类函数,而是对捕获此组合的类型进行操作的普通函数:
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)
Run Code Online (Sandbox Code Playgroud)