我正在尝试使用类型定义一个简单的 Haskell 函数(m -> n -> l) -> (m -> n) -> m -> l。我认为它需要被定义为f g h x = f g (h x),但显然这不是真的。我怎样才能纠正这个功能?
根据签名,唯一合理的实现是:
f :: (m -> n -> l) -> (m -> n) -> m -> l
f g h x = g x (h x)
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为我们有两个函数g :: m -> n -> l和h :: m -> n,以及一个值x :: m。我们应该构造一个 type 的值l。执行此操作的唯一方法是使用该函数g。对于类型为 的参数,m我们可以使用x,对于第二个参数,我们需要一个类型为 的值n,我们没有这样的值,但我们可以通过应用hon来构造一个值x。由于h x具有类型h x :: n,因此我们可以将其用作 的第二个参数g。
(<*>) :: Applicative f => f (n -> l) -> f n -> f l该函数已经定义:它是with的特例f ~ (->) m。
Djinn是一个推理类型的工具,因此可以根据其签名生成函数定义。如果用 查询f :: (m -> n -> l) -> (m -> n) -> m -> l,我们会得到:
f :: (m -> n -> l) -> (m -> n) -> m -> l
f a b c = a c (b c)
Run Code Online (Sandbox Code Playgroud)
这是相同的函数(除了它使用其他变量名称)。
f :: (m -> n -> l) -> (m -> n) -> m -> l
f g h x = _
Run Code Online (Sandbox Code Playgroud)
现在您需要以某种方式使用这些参数。
g (_ :: m) (_ :: n) :: l
h (_ :: m) :: n
x :: m
Run Code Online (Sandbox Code Playgroud)
和g都h需要一个类型值m作为它们的第一个参数。幸运的是,我们正好有一个这样的值,因此很容易知道该怎么做。
g x (_ :: n) :: l
h x :: n
x :: m
Run Code Online (Sandbox Code Playgroud)
所以现在g仍然需要一个 type 的值n。我们再次很幸运,因为申请h已经x产生了这样的价值。
g x (h x) :: l
h x :: n
x :: m
Run Code Online (Sandbox Code Playgroud)
好的,现在我们有了 type 的东西l,这就是我们所需要的!
f g h x = g x (h x)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
171 次 |
| 最近记录: |