Haskell Arrows里面的元组

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)

为什么我会得到这个错误,我该怎么办,以避免它?

dfl*_*str 9

我们来看看类型snd:

snd :: (foo, x) -> x
Run Code Online (Sandbox Code Playgroud)

(为了清楚起见,我重命名了类型变量)

类型的状态是对于具有类型的元组,foox返回类型的东西x.这里要知道的重要事情是,虽然价值体系又名.运行时Haskell是惰性的,Haskell的类型系统是严格的,这意味着双方的类型foox之前必须知道snd可以被调用.

在第一种情况下,当你刚才有一个时Num b => (b -> b, String),调用snd会留下b含糊不清的,因为你没有在任何地方提到它的具体类型,并且它不能从返回类型中推断出来,因为foo ~ b它不同于x.换句话说:因为(b, b)可以是任何数字类型的元组,并且类型检查器无法弄清楚哪一个,它是不明确的.这里的诀窍是我们将Haskell的默认规则启动,这表明如果数字类型不明确,它应该默认为Integer.如果您已经发出警告-Wall,那么就会说这种情况正在发生.所以,我们的类型变成(Integer -> Integer, String)并且snd可以调用.

在第二种情况下,但是,我们仍然设法推断b通过默认的规则,但没有默认Arrowa,所以我们就完蛋了!您必须明确指定所需的箭头才能继续!您可以通过首先使用其他位置的值来执行此操作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关键字可以帮助你.

  • 像`class Boolish a where toBool :: a - > Bool; foo :: Boolish a =>(a,b) - > b; foo(a,b)= if toBool a then b else undefined`是可以想象的,因此函数的结果可能取决于模糊参数.在这种情况下,`snd`的特殊外壳会很奇怪. (2认同)