2016-05-30 2 views
3

Я тренируюсь для экзамена Haskell через 2 недели. Теперь я делаю некоторые упражнения, но я застрял на этом.Реализация выбора более 2 объективов в haskell

Реализовать функцию choosing, которая дается 2 линзы и должен вернуть новый объектив, который работает с Either -значения.

Я дал этот код:

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 для решения этой проблемы, но я не знаю, как объединить эти 2 объектива.

Таким образом, с помощью @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))) 
+0

Если вам не повезло и вы хотите увидеть решение, следуйте этой ссылке (http://lpaste.net/6450842794700308480) и прочитайте действительно [хорошая статья] (https://artyom.me/lens-over- чай-1) о линзах с точными вашими упражнениями в нем – klappvisor

+0

@klappvisor: спасибо! Статья действительно удобна :) –

ответ

3

Это большая проблема, потому что упражнения вы даже не должны ничего знать о линзах для реализовать решение. Вы можете просто следовать этим типам.

choosing :: Lens s1 a -> Lens s2 a -> Lens (Either s1 s2) a 
choosing lns1 lns2 = undefined 

Тип возвращаемого Lens (Either s1 s2) a является псевдонимом для forall f . Functor f => (a -> f a) -> Either s1 s2 -> f (Either s1 s2), чтобы вы знали, что вы должны вернуть какую-то функцию, которая принимает два параметра:

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).

+0

Большое спасибо! Это действительно четкое объяснение :) –