uncurry($)做什么? [英] What does uncurry ($) do?

查看:104
本文介绍了uncurry($)做什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一些excersises,我必须添加一个函数的类型并解释它的作用。我坚持这样做:

  phy = uncurry($)

根据GHCi的类型是 phy ::(a - > b,a) - > B'/ code>。我的haskell知识是基础知识,所以我真的不知道它的作用。 我们来系统地说明类型部分。我们将从 uncurry ($)类型开始:

  uncurry ::(a  - > b  - > c) - > (a,b)→> c 
($)::(a - > b) - > a - > b

由于目标表达式有($)作为 uncurry 的参数,让我们排列它们的类型以反映它:

  uncurry ::(a  - > b  - > c) - > (a,b)→> c 
($)::(a - > b) - > a - > b

整个($)与第一个参数类型 uncurry 对齐,并且($)的参数和结果类型与那些 uncurry 的第一个参数,如图所示。这是通信:

  uncurry's a< ==> ($)的a  - > b 
uncurry的b< ==> ($)的a
uncurry的c< ==> ($)'sb

这有点令人困惑,因为 a <一个类型中的code>和 b 类型变量与其他类型变量不一样(就像 x in plusTwo x = x + 2 中的 x 不同= x * 2 )。但是我们可以重写这些类型来帮助理解这一点。在这样简单的Haskell类型签名中,只要你看到一个类型变量,你就可以用任何其他类型替换它所有的类型变量来得到一个有效的类型。如果您选择新鲜类型的变量(类型变量不会出现在原始的任何位置),您将得到一个类似的类型(可以转换回原始类型) ;如果你选择一种非新鲜的类型,你会得到一个专门的 版本的原始版本,它适用于更窄范围的类型。



但无论如何,让我们将它应用于 uncurry ::

 类型 - 替代a ==> x,b ==> y,c ==> z:
uncurry ::(x - > y - > z) - > (x,y)→> z

让我们使用重写的类型重新排列:

  uncurry ::(x  - > y  - > z) - > (x,y)→> z 
($)::(a - > b) - > a - > b

现在很明显: x< ==> a - > b y< ==> a z< ==> B'/ code>。现在,用 uncurry 的类型变量代替($)中的对应类型,我们得到:

  uncurry ::((a  - > b) - > a  - > b) - > (a  - > b,a) - > b 
($)::(a - > b) - > a - > b

最后:

  uncurry($)::(a  - > b,a) - > b 






这就是你如何确定类型的方法。它如何做?那么,在这种情况下做到这一点的最好方法是查看类型并仔细考虑它,弄清楚我们必须编写什么才能获得该类型的函数。让我们用这种方式重写它,让它更加神秘:

  mystery ::(a  - > b,a) - > b 
mystery = ...

由于我们知道 mystery 是一个参数的函数,我们可以扩展这个定义来反映:

  mystery x =。 .. 

我们也知道它的参数是一对,所以我们可以扩大一点:

  mystery(x,y)= ... 

由于我们知道 x 是一个函数,而 y :: a ,我喜欢使用 f 来表示function,并将变量命名为它们的类型 - 这有助于我对函数进行推理,所以让我们这样做吧: p>

  mystery(f,a)= ... 

现在,我们把什么放在右边?我们知道它的类型必须是 b ,但我们不知道 b> 是什么类型调用者选择,所以我们不能知道)。所以我们必须以某种方式使用我们的函数 f :: a - >来创建一个 b b 和值 a :: a 。啊哈!我们可以用这个值调用这个函数:

  mystery(f,a)= fa 

我们写了这个函数,而没有看 uncurry($),但事实证明,它和 uncurry($)做同样的事情,我们可以证明它。让我们从 uncurry ($)的定义开始:

  uncurry f(a,b)= fab 
f $ a = fa

现在,用等于等于:

  uncurry($)(f,a)=( $)fa  -  uncurry的定义,从左到右
= f $ a - Haskell语法规则
= fa - 定义($),从左到右
= mystery(f ,a) - 神秘的定义,从右到左

在Haskell中不明白的就是尝试编写一些具有该类型的代码。 Haskell与其他语言不同,因为这往往是比尝试阅读代码更好的策略。

I'm doing some excersises where I have to add a function's type and explain what it does. I'm stuck with this:

phy = uncurry ($)

The type, according to GHCi is phy :: (a -> b, a) -> b. My haskell knowledge is basic so I really have no idea what it does.

解决方案

Let's spell out the type part systematically. We'll start with the types of uncurry and ($):

uncurry :: (a -> b -> c) -> (a, b) -> c
($)     :: (a -> b) -> a -> b

Since the target expression has ($) as the argument of uncurry, let's line up their types to reflect this:

uncurry :: (a       -> b -> c) -> (a, b) -> c
($)     :: (a -> b) -> a -> b

The whole type of ($) lines up with the first argument type of uncurry, and the argument and result types of ($) line up with those of uncurry's first argument as shown. This is the correspondence:

uncurry's a  <==> ($)'s a -> b
uncurry's b  <==> ($)'s a
uncurry's c  <==> ($)'s b

This is kinda confusing, because the a and b type variables in one type are not the same as in the other (just like the x in plusTwo x = x + 2 is not the same as the x in timesTwo x = x * 2). But we can rewrite the types to help up reason about this. In simple Haskell type signatures like this, any time you see a type variable you can replace all of its occurrences with any other type get a valid type as well. If you pick fresh type variables (type variables that don't appear anywhere in the original), you get an equivalent type (one that can be converted back to the original); if you pick a non-fresh type you get a specialized version of the original that works with a narrower range of types.

But anyway, let's apply this to the type of uncurry::

-- Substitute a ==> x, b ==> y, c ==> z:
uncurry :: (x -> y -> z) -> (x, y) -> z

Let's redo the "line up" using the rewritten type:

uncurry :: (x       -> y -> z) -> (x, y) -> z
($)     :: (a -> b) -> a -> b

Now it's obvious: x <==> a -> b, y <==> a and z <==> b. Now, substituting uncurry's type variables for their counterpart types in ($), we get:

uncurry :: ((a -> b) -> a -> b) -> (a -> b, a) -> b
($)     ::  (a -> b) -> a -> b

And finally:

uncurry ($) :: (a -> b, a) -> b


So that's how you figure out the type. How about what it does? Well, the best way to do that in this case is to look at the type and think about it carefully, figuring out what we'd have to write to get a function of that type. Let's rewrite it this way to make it more mysterious:

mystery :: (a -> b, a) -> b
mystery = ...

Since we know mystery is a function of one argument, we can expand this definition to reflect that:

mystery x = ...

We also know that its argument is a pair, so we can expand a bit more:

mystery (x, y) = ...

Since we know that x is a function and y :: a, I like to use f to mean "function" and to name variables the same as their type—it helps me reason about the functions, so let's do that:

mystery (f, a) = ...

Now, what do we put in the right hand side? We know it must be of type b, but we don't know what type b is (it's actually whatever the caller chooses, so we can't know). So we must somehow make a b using our function f :: a -> b and value a :: a. Aha! We can just call the function with the value:

mystery (f, a) = f a

We wrote this function without looking at uncurry ($), but it turns out that it does the same thing as uncurry ($) does, and we can prove it. Let's start with the definitions of uncurry and ($):

uncurry f (a, b) = f a b
f $ a = f a

Now, substituting equals for equals:

uncurry ($) (f, a) = ($) f a         -- definition of uncurry, left to right
                   = f $ a           -- Haskell syntax rule
                   = f a             -- definition of ($), left to right
                   = mystery (f, a)  -- definition of mystery, right to left

So one way to attack a type that you don't understand in Haskell is to just try and write some code that has that type. Haskell is different from other languages in that very often this is a better strategy than trying to read the code.

这篇关于uncurry($)做什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆