如何"compose" iso的?

How to "compose" Iso's?

这是我的类型:

newtype SaneDate = SaneDate UniversalTime
   deriving (Show, Eq, Typeable, Generic)
makeWrapped ''SaneDate

现在我需要一个这种类型的 iso:

reprBuild :: Iso' (Maybe UniversalTime) (Fist SaneDate)

我这样做了:

reprBuild = iso
   (\ t -> First (SaneDate <$> t) )
   (\ sane_first -> fmap (^. _Wrapped) $ getFirst sane_first  )

但我觉得我工作非常努力。有没有一种(更短的)方式将 reprBuild iso 写成事物的组合?

使用safe coercions:

import Data.Coerce

reprBuild2 :: Iso' (Maybe UniversalTime) (First SaneDate)
reprBuild2 = iso coerce coerce

它进行类型检查 -- 没有执行其他测试。

mapping 组合器可让您在任何函子(在本例中为 Maybe 函子)上提升 Iso

reprBuild' :: Iso' (Maybe UniversalTime) (Maybe SaneDate)
reprBuild' = mapping _Unwrapped

我们也可以利用 First 有一个 Wrapped 实例来获取你想要的 iso:

reprBuild :: Iso' (Maybe UniversalTime) (First SaneDate)
reprBuild = mapping _Unwrapped . _Unwrapped

您也可以使用强制同构:coerced 但这仅适用于新型包装器并且需要 ghc >= 7.10.

lenshave that built in的最新版本:

reprBuild = coerced

当然,这需要 safe coercions,它仅在 7.10 之后可用;为了向后兼容 .