2016-12-03 2 views
6

Существует ли такая вещь в прелюдии Хаскелла?Isomorphic `fmap` в Haskell

wfmap :: Functor f 
     => a 
     -> (a -> b) 
     -> (b -> a) 
     -> (b -> f b) 
     -> f a 
wfmap x u w g = fmap (w) (g (u x)) 

В проекте я работаю, я часто «преобразования» типа в другой, процесс это и «преобразование» его обратно.

+0

Разве не имеет смысла принимать 'x :: a' в качестве последнего аргумента? – leftaroundabout

+0

@leftaroundabout, о да, это так. Спасибо что подметил это. Но это просто псевдокод, чтобы объяснить мою проблему. Просто, у меня есть много функций и типов, которые используют шаблон, подобный этому, и мне интересно, есть ли лучший способ сделать это. – iluvAS

+2

Ваш 'wfmap' объявляет 5 аргументов в типе, но только 4 в определении. Я думаю, что у вас есть дополнительный аргумент типа 'a' в типе. – chepner

ответ

7

Упорядочивание аргументы, как предполагает leftaroundabout, позволяет для определения опрятнее:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap u w g = fmap w . g . u 

Что касается библиотеки поддержки, объектив обеспечивает nifty support for isomorphisms. Немного более широко, как отмечает Gurkenglas ...

Functor f => (b -> f b) -> a -> f a также называют Lens' a b и является центральной частью библиотеки объектива.

Без погружения в детали того, как и почему это работает, одним из следствий является то, что ваша функция может быть определена как:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap u w g = (iso u w) g 

Или даже:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap = iso 

wfmap просто (специализированная версия) iso, которая выдает функцию, которая может быть использована для преобразования функции b -> f b в «место назначения изоморфизма» на номер a -> f a, расположенный на изоморфизм "источник".

Также стоит отметить mapping, который может быть использован для несколько иной цели применения fmap на другой стороне изоморфизма:

GHCi> :t \u w g -> over (mapping (iso u w)) (fmap g) 
\u w g -> over (mapping (iso u w)) (fmap g) 
    :: Functor f => (s -> a) -> (b -> t) -> (a -> b) -> f s -> f t 
GHCi> :t \u w g -> under (mapping (iso u w)) (fmap g) 
\u w g -> under (mapping (iso u w)) (fmap g) 
    :: Functor f => (s -> a) -> (b -> a1) -> (a1 -> s) -> f b -> f a 

Наконец, следует отметить, что iso u w можно заменить любым Iso вы может найти в библиотеках или предопределено в другом месте.

+0

Спасибо за это! :) – iluvAS

Смежные вопросы