我正在做一些练习,我必须添加一个函数的类型并解释它的作用。我坚持这样:
phy = uncurry ($)
根据GHCi的类型是
phy :: (a -> b, a) -> b
。我的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 <==> ($)'s a -> b
uncurry's b <==> ($)'s a
uncurry's c <==> ($)'s b
这有点令人困惑,因为一种类型的
a
和b
类型变量与另一种类型不同(就像x
中的plusTwo x = x + 2
与x
中的timesTwo x = x * 2
不同)。但是,我们可以重写类型以帮助解决此问题。在像这样的简单Haskell类型签名中,任何时候只要看到类型变量,都可以用任何其他类型替换所有出现的类型变量,也可以获得有效的类型。如果选择新的类型变量(原始变量中没有出现的类型变量),则会得到同等类型(可以转换回原始变量的类型);如果选择非新鲜类型,则会获得原始版本的专用版本,该类型适用于较窄的类型。但是无论如何,让我们将其应用于
uncurry
::-- Substitute 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
。现在,在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
来表示“功能”,并使用与它们的类型相同的名称来命名它-这有助于我对这些功能进行推理,因此我们可以这样做:mystery (f, a) = ...
现在,我们在右边放什么呢?我们知道它必须是
b
类型,但是我们不知道b
是什么类型(实际上是调用者选择的任何类型,因此我们无法知道)。因此,我们必须以某种方式使用函数b
和值f :: a -> b
来制作a :: a
。啊哈!我们可以使用以下值调用该函数:mystery (f, a) = f a
我们编写此函数时没有考虑
uncurry ($)
,但事实证明它的作用与uncurry ($)
相同,并且我们可以证明这一点。让我们从uncurry
和($)
的定义开始:uncurry f (a, b) = f a b
f $ a = f a
现在,用等于代替等于:
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
因此,攻击您在Haskell中无法理解的类型的一种方法是仅尝试编写一些具有该类型的代码。 Haskell与其他语言的不同之处在于,通常这是比尝试阅读代码更好的策略。
关于haskell - uncurry($)有什么作用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15993186/