作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在检查以下代码示例,发现一旦实现“first”并成为Cartisian的成员,就很难弄清楚如何使用(->)和(Star f)。
有人可以为他们提供一些易于理解的示例吗?谢谢。
-- Intuitively a profunctor is cartesian if it can pass around additional
-- context in the form of a pair.
class Profunctor p => Cartesian p where
first :: p a b -> p (a, c) (b, c)
first = dimap swapP swapP . second
second :: p a b -> p (c, a) (c, b)
second = dimap swapP swapP . first
instance Cartesian (->) where
first :: (a -> b) -> (a, c) -> (b, c)
first f = f `cross` id
instance Functor f => Cartesian (Star f) where
first :: Star f a b -> Star f (a, c) (b, c)
first (Star f) = Star $ (\(fx, y) -> (, y) <$> fx) . (f `cross` id)
最佳答案
注意,提前发表意见!
断言者有点过于抽象。 IMO,我们首先应该谈论类别;实际上,大多数发音者都是类别,反之亦然。该profunctor类可能具有有效的用途,但实际上受到的限制更大,并且与 Hask 类别相关。我更愿意通过讨论其箭头构造函数是最后一个参数中的 Hask -functors和pænultimate参数中相反的 Hask -functors的类别来使之明确。是的,这是一个令人mouth舌的问题,但这就是重点:这实际上是一个非常具体的情况,而且通常事实证明您确实只需要一个不太具体的类别。
具体而言,Cartesian
更自然地被视为一类类别,而不是发音者:
class Category k => Cartesian k where
swap :: k (a,b) (b,a)
(***) :: k a b -> k a' b' -> k (a,a') (b,b')
first :: Cartesian k => k a b -> k (a,c) (b,c)
first f = f *** id
second :: Cartesian k => k a b -> k (c,a) (c,b)
second f = id *** f
id
。 (您还可以根据
***
,
second
和
first
来定义
second f=swap.first f.swap
和
f***g=first f.second g
,但这与IMO的纠缠不清。)
newtype LinearMap v w = LinearMap {
runLinearMap :: v->w -- must be linear, i.e. if v and w are finite-dimensional
-- vector spaces, the function can be written as matrix application.
}
dimag f g (LinearMap a) = LinearMap $ dimap f g a
,但这不会保留线性。但是,这是笛卡尔类别:
instance Category LinearMap where
id = LinearMap id
LinearMap f . LinearMap g = LinearMap $ f . g
instance Cartesian LinearMap where
swap = LinearMap swap
LinearMap f *** LinearMap g = LinearMap $ f *** g
.
有效地实现了矩阵乘法,并且
***
以类型安全的方式将
block diagonal matrix放在一起。
instance Cartesian (->)
确实是微不足道的。但是,我给出了线性映射的示例,以激发
Cartesian
类可以完成一些不需要它的琐碎工作。
Star
变得非常有趣。
newtype Star f d c = Star{runStar :: d->f c}
instance Monad f => Category (Star f) where
id = Star pure
Star f . Star g = Star $ \x -> f =<< g x
instance Monad f => Cartesian (Star f) where
swap = Star $ pure . swap
Star f *** Star g = Star $ \(a,b) -> liftA2 (,) (f a) (g b)
Star
是
kleisli category的前身,您可能已经听说过,它是使用monadic计算链接的一种方法。因此,让我们直接来看一个
IO
示例:
readFile' :: Star IO FilePath String
readFile' = Star readFile
writeFile' :: Star IO (FilePath,String) ()
writeFile' = Star $ uncurry writeFile
copyTo :: Star IO (FilePath, FilePath) ()
copyTo = writeFile' . second readFile'
class Profunctor p => Strong p where
first' :: p a b -> p (a, c) (b, c)
second' :: p a b -> p (c, a) (c, b)
copyTo :: Star IO (FilePath, FilePath) ()
copyTo = writeFile' . second' readFile'
Strong
而不是
Cartesian
。我仍然在使用
Category
组合。我相信,没有任何组成,我们将无法建立非常复杂的示例。
Category
的
Star
实例:在这里,我对
Monad f
的要求很高。对于profunctor实例,这不是必需的:这些仅需要
Functor f
。因此,对于大多数关注的
Star
例子,它是一个强大的发音器,您需要查看的不是函子/单子的基本函子。在Van Laarhoven
lenses中,与此类函子相关的重要应用程序以及这些函子的内部实现确实可能为强者提供了最有见地的例子。每当我浏览镜头库的源代码时,我都会一直感到头晕,但是我认为
Strong Indexed是一个非常有影响力的实例。
关于haskell - 笛卡尔(Profunctor)的例子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53777851/
我是一名优秀的程序员,十分优秀!