2017-09-13 76 views
3

我有以下类型:如何使用类型和为什么编译器抱怨无限类型?

newtype Moi s a = 
    Moi { runMoi :: s -> (a, s) } 

数据构造函数需要一个函数作为参数,它应该返回一个元组。

我尝试以下操作:

*OwnState> :t Moi (+1) 

编译器会抱怨:

*OwnState> :t (+1) 
(+1) :: Num a => a -> a 

类型a必须是制约:

<interactive>:1:6: error: 
    * Occurs check: cannot construct the infinite type: s ~ (a, s) 
     Expected type: s -> (a, s) 
     Actual type: (a, s) -> (a, s) 
    * In the first argument of `Moi', namely `(+ 1)' 
     In the expression: Moi (+ 1) 

(+1)类型签名首先看Num typeclass。

所以当我写Moi (+1)时,会发生什么,类型将如何替代?

让我们来分析错误信息作为下一步:

Occurs check: cannot construct the infinite type: s ~ (a, s) 

波浪号意味着~类型平等和编译器如何来的结论,即s具有相同的类型(a, s)

我想,上面的例子中的类型替代工作在这样:

n -> n "Type of (+1) 
| | 
s -> (a, s) 

然后s变得(a, s)和论证s ~ (a, s)是真实的。

(a, s) -> (a, s) 

但我看不出来,为什么它是无限的类型。

+1

因为's'上的左侧和右侧都发生它是无限的'〜'而不是在语义部分。因此,在一次置换后,它是'〜(a,s)〜(a,(a,s))'等。 –

+1

's〜(a,s)'不正确 - 统一失败检查“步骤。事实上,没有类型'T',其中'(a,T)'仍然是相同的类型:第二个直观地包含另外一个'a'。这就像解决数字上的'n = n + 1'一样:除非你以某种方式允许“无限”作为数字,否则它是无法解决的。 – chi

+0

@Willem Van Onsem您可以为我这样的学习者展示如何替换一个类型。我看到很多案例,如何替代作品,但不知道,如果我是对的。 –

回答

7

但我看不出来,为什么它是无限的类型。

因为s发生在类型相等~的左侧和右侧,并且这是递归方式。一个替代后,我们有:

s ~ (a,s) 

但需要注意的是s(a,s)也应该被替换,所以:

s ~ (a,s) ~ (a,(a,s)) ~ (a,(a,(a,s))) ~ ... 

因此,为了构建这种类型的话,就会造成一种具有无限嵌套2元组。 Haskell无法处理这种类型。

Moi (+1)只是不符合这个“状态monad”的规格。你可能想使用:

Moi (\x -> (x,x+1)) 

或:

Moi (ap (,) (1 +)) 
相关问题