【问题标题】:Function to automatically unwrap / rewrap values in haskell?在haskell中自动解包/重新包装值的功能?
【发布时间】:2020-04-16 02:18:48
【问题描述】:

我做了一个函数如下:

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) -> ... 并且只有一个双射函数的情况下实现这一目标,但我也不确定如何做到这一点。

干杯!

【问题讨论】:

  • 是的,readshow 周围的括号不需要。不过,您的另一个问题是题外话。
  • 你可以写pen read show (\x -> x + 1)。该空间用于调用函数。
  • 啊,那只是我是个白痴,我已经编辑了问题以提出主要问题。谢谢。
  • 这是Profunctorial dimap,它在理论上很重要,但不在标准库中。
  • @HTNW 我认为dimap 非常好,即使profunctors 是第三方,也值得做出回答。

标签: haskell


【解决方案1】:

我认为这个函数的通用版本最标准的名称是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 重新生成该值。)

【讨论】:

    【解决方案2】:

    Haskell 的一个好处是可以很容易地查找您不知道其名称的函数,只需通过它们的类型即可。将(a -> b) -> (b -> a) -> (b -> b) -> a -> a 放入Hoogle 并尝试一下。在这种情况下,您会获得 4 个命中,但它们都在第三方库中。其中两个与您的函数执行完全相同的操作,两个几乎相同但更严格。

    另外,请注意,您的函数的类型签名没有它可以的通用性,并且所有结果都有一个更通用的:(a -> b) -> (c -> d) -> (b -> c) -> a -> d。使用不太通用的类型签名有点危险,因为它允许编译器捕获的错误。例如,pen conv rev app = rev . conv 是错误的,因为它跳过了app。使用您的类型签名,这可以很好地编译,但您会遇到运行时错误。使用更通用的类型签名,这将是在编译时捕获的类型错误。

    【讨论】:

    • 酷!有没有一种方法我也可以搜索某种只需要一个转换器函数的双射版本?对不起,如果我问错了问题,我还在学习(:
    • @insou 你怎么认为编译器会自动知道你给它的任意函数的逆?
    • 啊,我认为可能有某种类型的可逆函数可以满足你必须提供反转的类型?可能类似于证明类型是单子?但我想我不知道我在说什么:p
    • 可能有Iso之类的东西,但base中没有,绝对不简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    相关资源
    最近更新 更多