在haskell中实现2个以上镜头的选择

在haskell中实现2个以上镜头的选择,haskell,lenses,Haskell,Lenses,我正在练习两周后的Haskell考试。现在我正在做一些练习,但我被困在这个练习上了 执行一个功能选择给定2个镜头的,并返回一个新镜头,该镜头可与中的任何一个-值一起工作 我得到了以下代码: type Lens s a = forall f . Functor f => (a -> f a) -> s -> f s -------------------------------------------------------------- -- Lens s1 a

我正在练习两周后的Haskell考试。现在我正在做一些练习,但我被困在这个练习上了

执行一个功能
选择给定2个镜头的
,并返回一个新镜头,该镜头可与
中的任何一个
-值一起工作

我得到了以下代码:

type Lens s a = forall f . Functor f => (a -> f a) -> s -> f s

--------------------------------------------------------------
-- Lens s1 a             :: Functor f => a -> f a -> s1 -> f s1
-- Lens s2 a             :: Functor f => a -> f a -> s2 -> f s2
-- Lens (Either s1 s2) a :: Functor f => a -> f a -> (Either s1 s2) -> f (Either s1 s2)
--------------------------------------------------------------
choosing :: Lens s1 a -> Lens s2 a -> Lens (Either s1 s2) a
choosing lns1 lns2 = undefined
现在,我完全被卡住了。我想我应该用fmap来解决这个问题,但我不知道如何组合这两个镜头

因此,在@shang和@klappvisor的帮助下,我找到了这个问题的完整答案:

choosing :: Lens s1 a -> Lens s2 a -> Lens (Either s1 s2) a
choosing lns1 lns2 = (\func x -> case x of
                                Left value  -> (\z -> Left $ set lns1 z value) <$> (func (view lns1 value))
                                Right value -> (\z -> Right $ set lns2 z value) <$> (func (view lns2 value)))
选择::镜头s1a->镜头s2 a->镜头(s1或s2)a
选择lns1 lns2=(\func x->case x of
左值->(\z->左$set lns1 z值)(func(查看lns1值))
右值->(\z->右$set lns2 z值)(func(查看lns2值)))

这是一个很好的练习问题,因为你甚至不需要了解任何有关镜头的知识就可以实现解决方案。你可以按照类型来做

choosing :: Lens s1 a -> Lens s2 a -> Lens (Either s1 s2) a
choosing lns1 lns2 = undefined
返回类型
镜头(s1或s2)a
是所有f的别名。函子f=>(a->fa)->s1-s2->f(s1-s2)因此您知道必须返回某种函数,该函数包含两个参数:

choosing lns1 lns2 = \func x -> undefined
func
的类型是
(a->f a)
x
类型s1
的值。我们还不能用
func
做很多事情,但我们对
x
了解得足够多,我们可以在其上进行模式匹配:

choosing lns1 lns2 = \func x -> case x of
    Left l  -> undefined
    Right r -> undefined

现在,使用
lns1
lns2
func
以及类型
f
是一个函子(因此可以使用
fmap
)的知识,您只需实现case表达式的分支,以便两者都产生
f类型的值(s1-s2)

如果你运气不好,想看到解决方案,请遵循并认真阅读有关镜片的内容,并将你的练习准确地记录下来it@klappvisor:谢谢!这篇文章真的很方便:)非常感谢!这是一个非常清楚的解释:)