fro*_*h03 7 haskell functional-programming tuples arrows
我想要创建一个元组,它包含一个箭头和一个描述箭头的字符串.如果我用函数(而不是箭头)这样做,下面的工作就像预期的那样:
funTimes10 = (*10)
describe10 = "times 10"
tuple10 :: (Num b) => ((b -> b), String)
tuple10 = (,) funTimes10 describe10
Run Code Online (Sandbox Code Playgroud)
我可以使用fst和访问函数,并snd获取函数的描述字符串.
但是,如果我用箭头交换功能,如下所示:
aTuple10 :: (Arrow a, Num b) => (a b b, String)
aTuple10 = (,) (arr funTimes10) describe10
Run Code Online (Sandbox Code Playgroud)
fst 仍然有效并返回我的箭头,但是snd.我只收到此错误消息:
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)
Run Code Online (Sandbox Code Playgroud)
为什么我会得到这个错误,我该怎么办,以避免它?
我们来看看类型snd:
snd :: (foo, x) -> x
Run Code Online (Sandbox Code Playgroud)
(为了清楚起见,我重命名了类型变量)
类型的状态是对于具有类型的元组,foo并x返回类型的东西x.这里要知道的重要事情是,虽然价值体系又名.运行时Haskell是惰性的,Haskell的类型系统是严格的,这意味着双方的类型foo和x之前必须知道snd可以被调用.
在第一种情况下,当你刚才有一个时Num b => (b -> b, String),调用snd会留下b含糊不清的,因为你没有在任何地方提到它的具体类型,并且它不能从返回类型中推断出来,因为foo ~ b它不同于x.换句话说:因为(b, b)可以是任何数字类型的元组,并且类型检查器无法弄清楚哪一个,它是不明确的.这里的诀窍是我们将Haskell的默认规则启动,这表明如果数字类型不明确,它应该默认为Integer.如果您已经发出警告-Wall,那么就会说这种情况正在发生.所以,我们的类型变成(Integer -> Integer, String)并且snd可以调用.
在第二种情况下,但是,我们仍然设法推断b通过默认的规则,但没有默认Arrow的a,所以我们就完蛋了!您必须明确指定所需的箭头才能继续!您可以通过首先使用其他位置的值来执行此操作aTuple10:
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
Run Code Online (Sandbox Code Playgroud)
...或者你可以只指定你想要的类型:
print $ snd (aTuple10 :: (Int -> Int, String))
Run Code Online (Sandbox Code Playgroud)
PS如果你想更改模糊数字的默认类型,default关键字可以帮助你.