haskell - 在haskell中自动解包/重新包装值的功能?

标签 haskell

我做了一个函数如下:

pen :: (a -> b) -> (b -> a) -> (b -> b) -> a -> a
pen conv rev app = rev . app . conv

具体用法如下:

pen read show (\x -> x + 1) "5"
"6"

我对 Haskell 很陌生,我想知道 Haskell 标准库中是否存在这样的函数以及它的名称,因为我在 Hoogle 上找不到它。

我还假设有一些方法可以在没有 (a -> b) -> (b -> a) -> ... 并且只有一个双射函数的情况下实现这一目标,但我也不确定如何做到这一点。

干杯!

最佳答案

我认为这个函数的通用版本最标准的名称是dimap。不幸的是,它没有出现在 Hoogle 搜索中,因为 Hoogle lacks support for instances involving (->) .

无论如何,dimap 是一个类型类方法(对于 Profunctor 类),所以它比你想要的更通用(同样的方式 fmap 会比寻找 map 的人实际想要的更通用)。专门用于函数的 Profunctor 实例,它仍然比您想要的更通用,因为它允许将其输入和输出参数任意转换为任何类型,因此它的类型签名专门用于功能的是:

dimap :: (a -> b) -> (c -> d) -> (b -> c) -> (a -> d)

这显然可以进一步专门用于您想要的功能 pen:

dimap :: (a -> b) -> (b -> a) -> (b -> b) -> (a -> a)

它不在 base 中,但它包含在 lens 包或独立的 profunctors 包中:

> import Data.Profunctor   -- from "profunctors"
> dimap read show (\x -> x + 1) "5"
"6"

a -> b 类型的 Haskell 函数显然不能是“双射的”,但如果你使用 lens 包,Iso表示一个双射函数。

你可以定义一个 Iso 从一个函数和它的逆写:

> import Control.Lens
> showRead = iso show read

要使用此Iso 作为包装器/解包器应用函数,您可以使用镜头函数under :

> under showRead (+1) "5"
"6"

我想值得注意的是,showRead 可能不是一个很好的 Iso(即不完全合规),因为 showread 不是完美的逆。 (也就是说,一些 show 实例产生的值不能被 read 返回以重现该值。)

关于haskell - 在haskell中自动解包/重新包装值的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61234320/

相关文章:

haskell - 生成元组列表时内存泄漏

haskell - 在 Haskell 中将 IO 字符串写入标准输出

haskell - 这个例子似乎打破了 $ 的类型 sig,它有效

haskell - 使用列表理解进行素因数分解

haskell - 内存后续折叠调用

java - 如何将这个简单的 OOP 程序转换为函数式编程语言?

haskell - Haskell 中签名的实现

haskell - Snap 0.9 路由行为

haskell - 如何为具有 kind (* -> *) -> * 的类型编写 aeson ToJSON 实例

Haskell 为自定义类型导出 Show