用于部分转换的光学元件

问题描述 投票:2回答:2

Prism类似于Iso,只是两次转换之一是部分转换。是否有光学器件可以同时进行两种转换?

当然可以创建类型(s -> Maybe a, b -> Maybe t),但我想知道这样的事情是否可以表示为Optic _ _

haskell lens lenses
2个回答
2
投票

您可以通过将Hask(例如Optic _ _,这是Iso定义为(s -> a, b -> t)的约束)取代了Hask的特征,从而将(s -> m a, b -> m t)(即Profunctor)概括为Iso超过Kleisli类别(此处为Optic monad)。

Maybe

[要构造这样的profunctor的一个例子,首先要使用我们要使用的伪isos类型class Monad m => KProfunctor m p where dimapM :: (s -> m a) -> (b -> m t) -> p a b -> p s t -- dimapM pure pure = id -- dimapM f g . dimapM h i = dimapM (h >=> f) (g >=> i) type Optic p s t a b = p a b -> p s t type KIso m s t a b = forall p. KProfunctor m p => Optic p s t a b ,然后将(s -> m a, b -> m t)s用作主要索引:

t
  • 要从data PseudoIso m a b s t = MkPseudoIso { toM :: s -> m a , fromM :: b -> m t } instance Monad m => KProfunctor m (PseudoIso m) where -- exercise for the reader 转到PseudoIso,请使用KIsodimapM的字段正是PseudoIso的参数的正确类型)
  • 要从dimapM转到KIso,请部分应用于身份PseudoIso

实际上,它不一定是Kleisli类别。任意类别PseudoIso a b a b上的profunctor都会为您提供一类(:->) :: k -> k -> Type形式的光学元件。

注意:您可以使用(s :-> a, b :-> t)定义Choice的实例,因此也许所有内容都应专门用于KProfunctor Maybe,以便可以合理地将Maybe作为Choice的超类添加,然后KProfunctorKIso的子类型。


0
投票

让我们看一下profunctor编码。更简单。

[PrismChoice的类,我们正在制作Prism的子类,因此Prisms是超类的自然选择:

Choice

如果我们尝试为class Choice p => Weird p where weird :: (s -> Maybe a) -> (b -> Maybe t) -> p a b -> p s t 编写实例,它将无法正常工作。因此,我们的新型光学器件不是p = (->)的超类。

层次结构可能看起来像:充其量可能看起来像(也许可以将Setter从而转换为Traversal的新光学元件吗?)

Lens

让我们尝试另一个具体的Weird。我将使用 Lens / \ Iso Traversal -> Setter \ / Prism \ Weird

中定义的类型

Profunctor用于实现my blog post: Glassery

ForgetM

[preview可用于在相反的方向上定义内容(不在type Optic' p s a = p a a -> p s s preview :: Optic' (ForgetM a) s a -> s -> Maybe a preview o = runForgetM (o (ForgetM Just)) newtype ForgetM r a b = ForgetM { runForgetM :: a -> Maybe r } instance Profunctor (ForgetM r) where dimap f _ (ForgetM p) = ForgetM (p . f) instance Choice (ForgetM r) where right' (ForgetM p) = ForgetM (either (const Nothing) p) instance Weird (ForgetM r) where weird sa _bt (ForgetM ab) = ForgetM $ \s -> sa s >>= ab 中:]]]

TaggedM

我们现在可以尝试这个。

简单的案例:

Glassery

Prisms可以用作新事物(事物repreview :: Optic' TaggedM s a -> a -> Maybe s repreview o a = unTaggedM (o (TaggedM (Just a))) newtype TaggedM a b = TaggedM { unTaggedM :: Maybe b } instance Profunctor TaggedM where dimap _sa bt (TaggedM b) = TaggedM (fmap bt b) instance Choice TaggedM where right' (TaggedM b) = TaggedM (fmap Right b) instance Weird TaggedM where weird _sa bt (TaggedM b) = TaggedM (b >>= bt) ):

*Main> preview (weird Just Just) 'x'
Just 'x'
*Main> repreview (weird Just Just) 'x'
Just 'x'

还有一个很好的对称right' = _Right

*Main> preview right' (Left 'x')
Nothing
*Main> preview right' (Right 'x')
Just 'x'

我们可以为其编写Profunctor实例:

newtype Re p s t a b = Re { runRe :: p b a -> p t s }

instance Profunctor p => Profunctor (Re p s t) where
    dimap f g (Re p) = Re (p . dimap g f)

instance Cochoice p => Choice (Re p s t) where
    right' (Re p) = Re (p . unright)

instance Choice p => Cochoice (Re p s t) where
    unright (Re p) = Re (p . right')

并且我们注意到,我们需要添加Weird作为instance Weird p => Weird (Re p s t) where weird sa bt (Re p) = Re (p . weird bt sa) 的超类:

Cochoice

这看起来很有希望。


van-Laarhoven。这很棘手。

比较profunctor和VL编码中的Weird

class (Choice p, Cochoice p) => Weird p where
    weird :: (s -> Maybe a) -> (b -> Maybe t) -> p a b -> p s t

一个好的开始是假设此Prism看起来像

type PrismVL s t a b = forall f p. (Choice p, Applicative f) => p a (f b) -> p s (f t)
type PrismP  s t a b = forall   p. (Choice p)                => p a    b  -> p s    t

也许我们也需要加强Weird约束。

但是我有一些东西要您尝试。还有一个悬而未决的问题是,这种新型type WeirdOptic s t a b = forall p f. (Weird p, Applicative f) => Optic p f s t a b 光学元件背后的直觉是什么?以及它应具有的定律(成为光学器件,而不仅仅是两个功能砸在一起)。感觉比尝试进行类似的f / Weird光学比Monad还要漂亮的东西很难,但也许也会奏效。

© www.soinside.com 2019 - 2024. All rights reserved.