简体   繁体   English

另一个无限类型错误

[英]Yet another infinite type error

I'm trying to create a function that composes a function f with a function g that takes multiple arguments. 我正在尝试创建一个将函数f与带有多个参数的函数g组合在一起的函数。

c :: (a -> b) -> (c -> a) -> c -> b
c x y z = x(y(z))
lift = c c

(lift $ lift $ lift ... c) creates the desired function: (lift $ lift $ lift ... c)创建所需的功能:

*Main> (lift $ lift $ lift $ lift $ lift $ c) (\x -> x+2) (\x y z a b c -> x*y*z-(a*b*c)) 1 2 3 4 5 6
-112

However, when I attempt to define a function to produce a function that takes f, g, then n arguments (to save typing), the following error occurs: 但是,当我尝试定义一个函数以产生一个接受f,g和n个参数的函数(以保存输入)时,会发生以下错误:

cn 1 = c
cn k = lift (cn(k-1))
<interactive>:9:1: error:
    * Occurs check: cannot construct the infinite type: a ~ c0 -> a
      Expected type: t -> (a -> b) -> a -> b
        Actual type: t -> (a -> b) -> (c0 -> a) -> c0 -> b
    * Relevant bindings include
        cn :: t -> (a -> b) -> a -> b (bound at <interactive>:9:1)

Why does this error occur, and how might I resolve it? 为什么会发生此错误,我该如何解决?

You cannot make polyvariadic functions in Haskell without typeclasses. 没有类型类,就不能在Haskell中进行多元函数。

When you try to make a function that takes either one or two arguments, you try to make a function of type a -> b and a -> p -> b . 当您尝试制作一个带有一个或两个参数的函数时,您尝试制作一个类型a -> ba -> p -> b的函数。 Hence, the compiler must infer that the type b is equivalent to p -> b , so the type of the function becomes a -> p -> p -> p -> ... . 因此,编译器必须推断类型b等于p -> b ,因此函数的类型变为a- a -> p -> p -> p -> ... In other words, an infinite type. 换句话说,是无限类型。

A similar problem occurs when you try to make this function. 当您尝试使用此功能时,也会发生类似的问题。 The first line is fine: 第一行很好:

cn 1 = c

This would imply something like cn :: Int -> (b -> c) -> (a -> b) -> a -> c . 这意味着类似cn :: Int -> (b -> c) -> (a -> b) -> a -> c However, we now have a problem in the second line: 但是,第二行现在有一个问题:

cn k = lift (cn (k-1))

Since we know that cn :: Int -> (b -> c) -> (a -> b) -> a -> c , we must infer that cn (k-1) :: (b -> c) -> (a -> b) -> a -> c . 由于我们知道cn :: Int -> (b -> c) -> (a -> b) -> a -> c a- cn :: Int -> (b -> c) -> (a -> b) -> a -> c ,因此我们必须推断cn (k-1) :: (b -> c) -> (a -> b) -> a -> c However, since lift :: (x -> y -> z) -> x -> (w -> y) -> w -> z , we see that the return value must be of type (b -> c) -> (w -> a -> b) -> w -> c , which clashes with the original type declaration. 但是,由于lift :: (x -> y -> z) -> x -> (w -> y) -> w -> z ,我们看到返回值必须是(b -> c) -> (w -> a -> b) -> w -> c ,它与原始类型声明冲突。

TL;DR: you can't change the type of a Haskell function/value via values. TL; DR:您不能通过值更改Haskell函数/值的类型。 This means you can't write polyvariadic functions without certain tricks. 这意味着没有某些技巧就不能编写多元函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM