我无所事事并在Haskell中定义了一个for
函数,如下所示。
for :: (Ord i, Num i) => (i, i, i) -> b -> (i -> b -> b) -> b
for (init, incr, end) initState bodyFn = for' (init, initState) bodyFn
where
-- for' :: (Ord i, Num i) => (i, b) -> (i -> b -> b) -> b
for' (index, state) bodyFn | if incr > 0 then index >= end else index <= end = state
for' (index, state) bodyFn = for' (index + incr, bodyFn index state) bodyFn
工作正常。
> for (1, 1, 10) 0 (\i b -> i+b)
45
我想声明where
函数的类型。 (正如你所看到的,它被注释掉了。)当我删除注释标记时,我收到此错误消息。
Couldn't match expected type ‘i1’ with actual type ‘i’
‘i’ is a rigid type variable bound by
the type signature for:
for :: forall i b.
(Ord i, Num i) =>
(i, i, i) -> b -> (i -> b -> b) -> b
at while.hs:5:8
‘i1’ is a rigid type variable bound by
the type signature for:
for' :: forall i1 b1.
(Ord i1, Num i1) =>
(i1, b1) -> (i1 -> b1 -> b1) -> b1
at while.hs:9:11
• In the second argument of ‘(>=)’, namely ‘end’
In the expression: index >= end
In the expression: if incr > 0 then index >= end else index <= end
• Relevant bindings include
bodyFn :: i1 -> b1 -> b1 (bound at while.hs:10:23)
index :: i1 (bound at while.hs:10:9)
for' :: (i1, b1) -> (i1 -> b1 -> b1) -> b1 (bound at while.hs:10:3)
bodyFn :: i -> b -> b (bound at while.hs:6:34)
end :: i (bound at while.hs:6:19)
incr :: i (bound at while.hs:6:13)
我猜这个问题与for'
函数将其中一个变量与for
函数中的变量进行比较这一事实有关 - 并且还将其中一个变量添加到来自for
函数的变量。它们应该是同一类型。有没有办法说出来?或者是否有另一种方式来声明for'
函数的类型?
感谢。
P.S。我知道我可以将for'
函数声明为顶级函数并将其传递给相关变量,但我想知道是否有办法使用此结构编写有效声明。
P.P.S基本上同样的问题被问到here,但答案是摆脱嵌套函数的声明。写一个有用的方法吗?
答案 0 :(得分:2)
感谢jberryman,给Mismatch of rigid type variables的答案解决了这个问题。以下代码有效。 (请注意,bodyFn
也不需要传递。)
{-# LANGUAGE ScopedTypeVariables #-}
for :: forall i b. (Ord i, Num i) => (i, i, i) -> b -> (i -> b -> b) -> b
for (init, incr, end) initState bodyFn = for' (init, initState)
where
for' :: (Ord i, Num i) => (i, b) -> b
for' (index, state) | if incr > 0 then index >= end else index <= end = state
for' (index, state) = for' (index + incr, bodyFn index state)