在 haskell 中实现选择 2 个以上的镜头
Implement choosing over 2 lenses in haskell
我正在为 2 周后的考试 Haskell 练习。现在我正在做一些练习,但我坚持这个。
Implement a function choosing
that is given 2 lenses and should return a new lens that works with Either
-values.
我得到了这个代码:
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)))
这是一个很好的练习题,因为你甚至不需要了解任何关于镜头的知识就可以解决这个问题。你可以只关注类型。
choosing :: Lens s1 a -> Lens s2 a -> Lens (Either s1 s2) a
choosing lns1 lns2 = undefined
return 类型 Lens (Either s1 s2) a
是 forall f . Functor f => (a -> f a) -> Either s1 s2 -> f (Either s1 s2)
的别名,因此您知道您必须 return 某种带有两个参数的函数:
choosing lns1 lns2 = \func x -> undefined
func
的类型是 (a -> f a)
,x
是 Either s1 s2
类型的值。我们还不能用 func
做很多事情,但我们对 x
了解足够多,我们可以对其进行模式匹配:
choosing lns1 lns2 = \func x -> case x of
Left l -> undefined
Right r -> undefined
现在,使用 lns1
、lns2
、func
和类型 f
是函子的知识(因此您可以使用 fmap
)您只需要实现 case 表达式的分支,以便两者都产生 f (Either s1 s2)
.
类型的值
我正在为 2 周后的考试 Haskell 练习。现在我正在做一些练习,但我坚持这个。
Implement a function
choosing
that is given 2 lenses and should return a new lens that works withEither
-values.
我得到了这个代码:
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)))
这是一个很好的练习题,因为你甚至不需要了解任何关于镜头的知识就可以解决这个问题。你可以只关注类型。
choosing :: Lens s1 a -> Lens s2 a -> Lens (Either s1 s2) a
choosing lns1 lns2 = undefined
return 类型 Lens (Either s1 s2) a
是 forall f . Functor f => (a -> f a) -> Either s1 s2 -> f (Either s1 s2)
的别名,因此您知道您必须 return 某种带有两个参数的函数:
choosing lns1 lns2 = \func x -> undefined
func
的类型是 (a -> f a)
,x
是 Either s1 s2
类型的值。我们还不能用 func
做很多事情,但我们对 x
了解足够多,我们可以对其进行模式匹配:
choosing lns1 lns2 = \func x -> case x of
Left l -> undefined
Right r -> undefined
现在,使用 lns1
、lns2
、func
和类型 f
是函子的知识(因此您可以使用 fmap
)您只需要实现 case 表达式的分支,以便两者都产生 f (Either s1 s2)
.