Haskell Setter / over с несколькими целями? [Дубликат]

Вне прямых ответов здесь следует отметить другое ключевое различие между python 2 и 3. Официальная версия python wiki затрагивает почти все основные отличия и фокусируется на том, когда вы должны использовать либо версий. Это сообщение в блоге также прекрасно описывает объяснение текущей вселенной python и как-то нераскрытую загадку перехода на python 3.

Насколько я могу судить, вы начинаете изучите язык python. Вы должны рассмотреть вышеупомянутые статьи, прежде чем продолжить путь python 3. Вам не только придется изменить какой-то из ваших синтаксисов, вам также нужно будет подумать о том, какие пакеты будут доступны вам (преимущество python 2) и потенциальные оптимизации, которые могут быть сделаны в вашем коде (преимущество python 3) .

7
задан Simon Shine 10 April 2016 в 07:44
поделиться

2 ответа

Как объяснил фадедж, в этом нет законопослушного способа сделать это. Тем не менее, вы можете сделать это в любом случае и предупредить своих пользователей, что им лучше быть осторожным только для применения к ортогональным объективам.

import Control.Lens
import Control.Arrow ((&&&))

fakeIt :: Lens' s x -> Lens' s y -> Lens' s (x,y)
fakeIt l1 l2 =
  lens (view l1 &&& view l2)
       (\s (x,y) -> set l1 x . set l2 y $ s)

Например:

Prelude Control.Lens A> set (fake _1 _2) (7,8) (1,2,3)
(7,8,3)
Prelude Control.Lens A> view (fake _1 _2) (1,2,3)
(1,2)
7
ответ дан dfeuer 27 August 2018 в 10:26
поделиться

В общем случае это невозможно. Вероятно, наиболее распространенный случай, когда у вас есть линзы для разных областей записи, линзы не пересекаются, поэтому вы можете сделать законный объектив. Но в целом это неправда. Вот почему комбинатор не предоставляется в библиотеках, даже его было бы легко написать.

Предположим, что существует lensProd. Достаточно взять одну и ту же линзу дважды:

_1 :: Lens' (a, b) a -- Simpler type

badLens :: Lens' (a, b) (a, a)
badLens = lensProd _1 _1

Тогда закон «Вы вернете то, что вы положили» не имеет. Это должно быть:

view badLens (set badLens (1, 2) (3, 4)) ≡ (1, 2)

Но это не может быть правдой, поскольку view badLens pair возвращает некоторое значение дважды: (x, x) для всех pair s.

@dfeuer дает пример, как определить lensProd.


Интересно, что двойное слово также нарушено. В общем случае вы не можете иметь законную сумму призмы:

{-# LANGUAGE RankNTypes #-}

import Control.Applicative
import Control.Lens

-- |
-- >>> :t sumPrism _Just _Nothing :: Prism' (Maybe a) (Either a ())
-- sumPrism _Just _Nothing :: Prism' (Maybe a) (Either a ())
--  :: (Applicative f, Choice p) =>
--     p (Either a ()) (f (Either a ())) -> p (Maybe a) (f (Maybe a))
--
sumPrism :: Prism' a b -> Prism' a c -> Prism' a (Either b c)
sumPrism ab ac = prism' build match where
    build (Left b)  = ab # b
    build (Right c) = ac # c

    match x = Left <$> x ^? ab <|> Right <$>  x ^? ac

-- The law
--
-- @
-- preview l (review l b) ≡ Just b
-- @
--
-- breaks with
--
-- >>> preview badPrism (review badPrism (Right 'x'))
-- Just (Left 'x')
-- 
badPrism :: Prism' a (Either a a)
badPrism = sumPrism id id

Как вы можете видеть, мы помещаем Right, но выходим из Left.

9
ответ дан phadej 27 August 2018 в 10:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: