What I want is to write something like this:
let (a,b) = if *condition* then (first, second) else (second, first)
I found out that I cannot write even this:
let (a,b) = (first,second)
It fails with an error:
<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
Very shortly, you try to construct Impredicative type which GHC cannot infer. You can do:
λ 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)
or
: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)
but you cannot do:
λ 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))
To isolate the issue, this works:
λ 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))
but when you try to bind that to pattern:
λ Control.Arrow > let (a, b) = p
it fails. Constraints are outside of the pair type, and are redundant for other halves of the pair, as
λ 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
works.
Simple example:
λ 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
One have to carry constraints over, but there is no a
in the type of ()
, i.e. Monoid a => ()
is ambigious type.
Note: let (a,b) = ((+), (*))
seems to work. I have no idea why and how Num
is treated specially:
λ 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)
...
It looks like you are running monomorphism restriction. This is just a limitation of Haskell's type inference and you can get around it by adding an explicit type signature.
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)
This code typechecks fine with the type signature for foo
but gives that "ambiguous variable" compilation error if you remove it.
BTW, the type signature I used was the one inferred by :t (first, second)
in GHCI. Since you want (first, second)
and (second, first)
to have the same type, you will probably want to use a more specific type in your annotation, such as the following one:
foo :: (Arrow a) => (a b b -> a (b, b) (b, b), a b b -> a (b, b) (b, b))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With