Как добавить аппликативный контекст в тип, ожидаемый от Lens 'MyDataType? - PullRequest
0 голосов
/ 09 января 2019

У меня есть функция, обобщенная на функцию func, которая должна быть применена к MyDataType1, а другая MyDataType1 похожа на эту

setThis :: (Functor f0, Applicative f0) => Lens' MyDataType1 (f0 Float) -> Float -> MyDataType1 -> MyDataType1 -> MyDataType1         
setThis func toThis dataType1 dataType2 = dataType2 & func %~ (\a -> (+) <$> a <*> delta
    where baseStat = dataType1 ^. func -- baseStat has type Maybe Float
          delta = (\a -> toThis * a) <$> baseStat -- also have type Maybe Float

где MyDataType1 (при использовании с print. Каждое числовое значение равно Float)

data MyDataType1 = MyDataType1 { _name = Just "First"
                               , _length = Just 5.5 
                               , _dmsTypes = Just
                                     ( DMS { _i = Just 1.9
                                           , _j = Nothing
                                           , _k = Just 95.9
                                           }
                                      )
                               }

Функция setThis имеет функцию записи по умолчанию, такую ​​как length, константа Float, набор данных для получения базового значения из и набор данных для изменения устанавливает _length в число, которое является суммой исходного значения и значения из другого набора, умноженного на некоторую константу.

Это работает так же, как я ожидаю, когда данная функция length.

То, что я хочу сделать, - это вести себя точно так же, когда передается функция, подобная (dmsTypes . _j), как в

setThis (dmsTypes . _Just . _j) 0.3 (someY) (someY) -- someY :: MyDataType1 

Хотя GHC выдает эту ошибку, если я делаю именно это

Could not deduce (Applicative f) arising from a use of ‘_Just’
  from the context: Functor f
    bound by a type expected by the context:
               Lens' MyDataType1 (Maybe Float)
Possible fix:
    add (Applicative f) to the context of
      a type expected by the context:
        Lens' MyDataType1 (Maybe Float)

И хотя кажется, что GHC точно знает, что я должен делать, я не знаю, как это сделать.

1 Ответ

0 голосов
/ 09 января 2019

Поскольку вещь, на которую указывает func, может не существовать, это должен быть обход (любое количество сфокусированных значений), а не линза (ровно одно сфокусированное значение).

Часть setThis, которая использует установщик (т. Е. (%~)), остается прежней, но вместо этого getter часть (т. Е. (^.)) должна использовать сгиб , с (^?). В этом случае dataType1 ^? func будет иметь два слоя Maybe, один из (^?) и один из func (в том, что в настоящее время f0), которые вы, вероятно, захотите сгладить с помощью join.

baseState = join (dataType1 ^? func)

Теперь f0 должно быть Maybe.

setThis :: Traversal' MyDataType1 (Maybe Float) -> ...
...