Control.Arrow:为什么"让(a,b)=(第一,第二)"失败?

时间:2016-06-13 18:29:25

标签: haskell functional-programming arrows

我想要写的是这样的东西:

let (a,b) = if *condition* then (first, second) else (second, first)

我发现即使这样我也写不出来:

let (a,b) = (first,second)

失败并显示错误:

 <interactive>:7:5:                                                                                                                          
Could not deduce (Arrow a0)                                                                                                             
from the context (Arrow a)
  bound by the inferred type for `a':
             Arrow a => a b c -> a (b, d) (c, d)
  at <interactive>:7:5-26
The type variable `a0' is ambiguous
When checking that `a' has the inferred type
  a :: forall (a :: * -> * -> *) b c d.
       Arrow a =>
       a b c -> a (b, d) (c, d)
Probable cause: the inferred type is ambiguous

<interactive>:7:5:
Could not deduce (Arrow a0)
from the context (Arrow a)
  bound by the inferred type for `b':
             Arrow a => a b c -> a (d, b) (d, c)
  at <interactive>:7:5-26
The type variable `a0' is ambiguous
When checking that `b' has the inferred type
  b :: forall (a :: * -> * -> *) b c d.
       Arrow a =>
       a b c -> a (d, b) (d, c)
Probable cause: the inferred type is ambiguous

2 个答案:

答案 0 :(得分:2)

很快,您尝试构建GHC无法推断的Impredicative类型。你可以这样做:

λ Control.Arrow > let (a,b) = (first, second) :: Arrow a => (a b b -> a (b, b) (b, b), a b b -> a (b, b) (b, b))
λ Control.Arrow > :t a
a :: Arrow a => a b b -> a (b, b) (b, b)
λ Control.Arrow > :t b
b :: Arrow a => a b b -> a (b, b) (b, b)

:set -XImpredicativeTypes 
λ Control.Arrow > let (a,b) = (first, second) :: (Arrow a => a b b -> a (b, b) (b, b), Arrow a => a b b -> a (b, b) (b, b))
λ Control.Arrow > :t a
a :: Arrow a => a b b -> a (b, b) (b, b)
λ Control.Arrow > :t b
b :: Arrow a => a b b -> a (b, b) (b, b)

但你不能这样做:

λ Control.Arrow > let (a,b) = (first, second) :: (Arrow a, Arrow a') => (a b b -> a (b, b) (b, b), a' b b -> a' (b, b) (b, b))

要解决问题,这可行:

λ Control.Arrow > let p = (first, second) :: (Arrow a, Arrow a') => (a b b -> a (b, b) (b, b), a' b b -> a' (b, b) (b, b));
λ Control.Arrow > :t p
p :: (Arrow a', Arrow a) =>
     (a b b -> a (b, b) (b, b), a' b b -> a' (b, b) (b, b))

但是当你尝试将它绑定到pattern时:

λ Control.Arrow > let (a, b) = p

失败了。约束在对类型之外,对于该对的其他一半是多余的,如

λ Control.Arrow > :set -XImpredicativeTypes 
λ Control.Arrow > let p = (first, second) :: (Arrow a => a b b -> a (b, b) (b, b), Arrow a => a b b -> a (b, b) (b, b))
λ Control.Arrow > let (a, b) = p

作品。

简单示例:

λ Prelude Data.Monoid > :t (mappend, ())
(mappend, ()) :: Monoid a => (a -> a -> a, ())
λ Prelude Data.Monoid > let (a, b) = (mappend, ())

<interactive>:12:5:
    No instance for (Monoid a0)
      arising from the ambiguity check for ‘b’
    The type variable ‘a0’ is ambiguous
    When checking that ‘b’ has the inferred type ‘()’
    Probable cause: the inferred type is ambiguous

必须对约束进行约束,但a的类型中没有(),即Monoid a => ()是暧昧类型。

注意:let (a,b) = ((+), (*))似乎有效。我不知道为什么以及如何特别对待Num

λ Prelude Data.Monoid > let x = () ::  Num a => ()
λ Prelude Data.Monoid > :t x
x :: ()
λ Prelude Data.Monoid > let x = () :: Monoid m => ()

<interactive>:12:9:
    No instance for (Monoid m0)
    ...

答案 1 :(得分:1)

看起来你正在运行monomorphism restriction。这只是Haskell类型推断的一个限制,您可以通过添加显式类型签名来解决它。

import Control.Arrow

foo :: (Arrow a, Arrow a1) => (a b c -> a (b, d) (c, d), a1 b1 c1 -> a1 (d1, b1) (d1, c1))
foo = (first, second)

此代码使用foo的类型签名进行类型检查,但是会给出&#34;模糊变量&#34;如果删除它,则会出现编译错误。

BTW,我使用的类型签名是GHCI中:t (first, second)推断的类型签名。由于您希望(first, second)(second, first)具有相同的类型,因此您可能希望在注释中使用更具体的类型,例如以下类型:

foo :: (Arrow a) => (a b b -> a (b, b) (b, b), a b b -> a (b, b) (b, b))