Haskell Arrows Inside Tuples

I want to split a tuple that contains an arrow and a string that describes the arrow. If I do this using functions (instead of arrows), then the following works:

funTimes10 = (*10) describe10 = "times 10" tuple10 :: (Num b) => ((b -> b), String) tuple10 = (,) funTimes10 describe10 

I can access the function using fst , and using snd get the function description string.

However, if I exchange a function with an arrow, as in the following:

 aTuple10 :: (Arrow a, Num b) => (abb, String) aTuple10 = (,) (arr funTimes10) describe10 
  • fst still works and returns my arrow, but
  • I do not get the description line with snd .

I got an error message:

 Ambiguous type variable `a0' in the constraint: (Arrow a0) arising from a use of `aTuple10' Probable fix: add a type signature that fixes these type variable(s) In the first argument of `snd', namely `aTuple10' In the expression: (snd aTuple10) In an equation for `it': it = (snd aTuple10) 

Why am I getting this error, and what should I do to avoid it?

+7
source share
2 answers

Let's look at the snd type:

 snd :: (foo, x) -> x 

(I renamed type variables for clarity)

What is a type state for a tuple with types foo and x , return something of type x . Something important to know here is that while the value system is aka. Haskell's runtime is lazy, a system like Haskell is strict, which means that both foo and x must be known before snd can be called.

In the first case, when you have only Num b => (b -> b, String) , calling snd will leave b ambiguous, because you will not specify its specific type anywhere, and it cannot be deduced from the returned type because that foo ~ b , which is different from x . In other words: since (b, b) can be a tuple of any type of number, and the type checker cannot determine which one is ambiguous. The trick here is that we will introduce default Haskell rules that state that if a numeric type is ambiguous, it should default to Integer . If you enabled warnings with -Wall , he would say that this is happening. So our type becomes (Integer -> Integer, String) and snd can be called.

However, in the second case, we still manage to draw b using the default rules, but by default there is no Arrow for a , so we’re stuck! You must explicitly indicate which arrow you want to continue! You can do this by first using the aTuple10 value somewhere else:

 let bla = aTuple10 -- We do this because `aTuple10` can have type variables, but `bla` cannot (by default) fst bla (23 :: Int) -- This fixes the type of `bla`, so that `a ~ (->)` and `b ~ Int` print $ snd bla -- So the arrow isn't ambiguous here 

... or you can just specify the type you want:

 print $ snd (aTuple10 :: (Int -> Int, String)) 

PS , if you want to change the type of ambiguous numbers by default, the default keyword can help you out.

+9
source

I tried to compile this:

 import Control.Arrow funTimes10 = (*10) describe10 = "times 10" tuple10 :: (Num b) => ((b -> b), String) tuple10 = (,) funTimes10 describe10 aTuple10 :: (Arrow a, Num b) => (abb, String) aTuple10 = (,) (arr funTimes10) describe10 

But I get this:

 Could not deduce (b ~ Integer) from the context (Arrow a, Num b) bound by the type signature for aTuple10 :: (Arrow a, Num b) => (abb, String) at D:\dev\haskell\arr_tuple.hs:10:1-42 `b' is a rigid type variable bound by the type signature for aTuple10 :: (Arrow a, Num b) => (abb, String) at D:\dev\haskell\arr_tuple.hs:10:1 Expected type: b -> b Actual type: Integer -> Integer In the first argument of `arr', namely `funTimes10' In the first argument of `(,)', namely `(arr funTimes10)' 

So, I assume that you need to decide which instance of the arrow you want to use. That is, you may need to specify a specific type of arr funTimes with annotation.

-one
source

All Articles