组合棱镜以关注一个值而不考虑分支
Combine prisms to focus on a value regardless of a branch
我有一个可能结果的总和类型,在每个结果中都有一个我想关注的"Result"。我知道如何从每个结果中得到 "Result"(为此我有一堆棱镜),但我不知道如何组合这些棱镜以便我可以从中获取 "Result"整个 sumtype,不用担心我在哪种情况下。
简化示例:
type OneAnother = Either Int Int
exampleOneAnother :: OneAnother
exampleOneAnother = Left 10
_one :: Prism' OneAnother Int
_one = _Left
_another :: Prism' OneAnother Int
_another = _Right
_result :: Lens' OneAnother Int
_result = ???
-- How can I combine _one and _another to get result regardless whether its left or right ?
这是迄今为止我得到的最好的。是的,unsafePartial
,显式大小写匹配...真的希望有更好的东西。
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter :: OneAnother -> Int
getter x@(Left _) = unsafePartial $ fromJust $ preview _one x
getter x@(Right _) = unsafePartial $ fromJust $ preview _another x
setter :: OneAnother -> Int -> OneAnother
setter (Left _) x = review _one x
setter (Right _) x = review _another x
一旦棱镜聚焦,它就会失去上下文。所以我看不到根据 _one
和 _another
定义 _result
的方法。但是你当然可以比诉诸 unsafePartial
:
做得更好
import Data.Lens.Lens (Lens', lens)
import Data.Profunctor.Choice ((|||), (+++))
type OneAnother = Either Int Int
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter = identity ||| identity
setter e x = (const x +++ const x) e
从 profunctor-lens
存储库中窃取:
-- | Converts a lens into the form that `lens'` accepts.
lensStore :: forall s t a b . ALens s t a b -> s -> Tuple a (b -> t)
lensStore l = withLens l (lift2 Tuple)
它没有以某种方式导出。在这种帮助下,以下解决方案应该足够通用:
import Prelude
import Control.Apply (lift2)
import Data.Lens.Common
import Data.Lens.Lens
import Data.Lens.Prism
import Data.Profunctor.Choice ((|||), (+++))
import Data.Tuple
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter = identity ||| identity
setter e x = (const x +++ const x) e
lensStore :: forall s t a b . ALens s t a b -> s -> Tuple a (b -> t)
lensStore l = withLens l (lift2 Tuple)
data ABC
= A Int
| B (Tuple Boolean Int)
| C OneAnother
lensABCInt :: Lens' ABC Int
lensABCInt = lens' case _ of
A i -> map A <$> lensStore identity i
B i -> map B <$> lensStore _2 i
C i -> map C <$> lensStore _result i
此处 ABC
是您的目标总和类型。只要它的每个变体都有一个镜头,您就拥有了一个整体的镜头。
我有一个可能结果的总和类型,在每个结果中都有一个我想关注的"Result"。我知道如何从每个结果中得到 "Result"(为此我有一堆棱镜),但我不知道如何组合这些棱镜以便我可以从中获取 "Result"整个 sumtype,不用担心我在哪种情况下。
简化示例:
type OneAnother = Either Int Int
exampleOneAnother :: OneAnother
exampleOneAnother = Left 10
_one :: Prism' OneAnother Int
_one = _Left
_another :: Prism' OneAnother Int
_another = _Right
_result :: Lens' OneAnother Int
_result = ???
-- How can I combine _one and _another to get result regardless whether its left or right ?
这是迄今为止我得到的最好的。是的,unsafePartial
,显式大小写匹配...真的希望有更好的东西。
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter :: OneAnother -> Int
getter x@(Left _) = unsafePartial $ fromJust $ preview _one x
getter x@(Right _) = unsafePartial $ fromJust $ preview _another x
setter :: OneAnother -> Int -> OneAnother
setter (Left _) x = review _one x
setter (Right _) x = review _another x
一旦棱镜聚焦,它就会失去上下文。所以我看不到根据 _one
和 _another
定义 _result
的方法。但是你当然可以比诉诸 unsafePartial
:
import Data.Lens.Lens (Lens', lens)
import Data.Profunctor.Choice ((|||), (+++))
type OneAnother = Either Int Int
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter = identity ||| identity
setter e x = (const x +++ const x) e
从 profunctor-lens
存储库中窃取:
-- | Converts a lens into the form that `lens'` accepts.
lensStore :: forall s t a b . ALens s t a b -> s -> Tuple a (b -> t)
lensStore l = withLens l (lift2 Tuple)
它没有以某种方式导出。在这种帮助下,以下解决方案应该足够通用:
import Prelude
import Control.Apply (lift2)
import Data.Lens.Common
import Data.Lens.Lens
import Data.Lens.Prism
import Data.Profunctor.Choice ((|||), (+++))
import Data.Tuple
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter = identity ||| identity
setter e x = (const x +++ const x) e
lensStore :: forall s t a b . ALens s t a b -> s -> Tuple a (b -> t)
lensStore l = withLens l (lift2 Tuple)
data ABC
= A Int
| B (Tuple Boolean Int)
| C OneAnother
lensABCInt :: Lens' ABC Int
lensABCInt = lens' case _ of
A i -> map A <$> lensStore identity i
B i -> map B <$> lensStore _2 i
C i -> map C <$> lensStore _result i
此处 ABC
是您的目标总和类型。只要它的每个变体都有一个镜头,您就拥有了一个整体的镜头。