【发布时间】:2019-04-11 18:54:57
【问题描述】:
抱歉,我以较小的方式涉足 Haskell,每 2 年一次,然后我无法理解它。
最好只做例子。
> {-# LANGUAGE MultiParamTypeClasses #-}
> {-# LANGUAGE ScopedTypeVariables #-}
> {-# LANGUAGE AllowAmbiguousTypes #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE FlexibleContexts #-}
> class Foo a b where
> foo :: a -> b
>
> class Bar a b where
> bar :: a -> b
> data A a = A a
> data B b = B b
> instance Foo (A a) a where
> foo (A a) = a
> instance Bar (B b) b where
> bar (B b) = b
所以,我认为我正在做的是创建数据类型,然后根据类中数据类型的成员资格定义两个函数......
所以这行得通....
> f1 x = foo x
> f2 x = bar x
> x1 :: String
> x1 = f1 $ A "1"
> x2 :: String
> x2 = f2 $ B "1"
简单...
担心 #1...如果我删除 x1 和 x2 的类型声明,ghc 会抱怨
• Ambiguous type variable ‘b1’ arising from a use of ‘f1’
prevents the constraint ‘(Foo (A [Char]) b1)’ from being solved.
Relevant bindings include x1 :: b1 (bound at catdog.lhs:27:3)
Probable fix: use a type annotation to specify what ‘b1’ should be.
These potential instance exist:
instance Foo (A a) a -- Defined at catdog.lhs:17:12
• In the expression: f1 $ A "1"
In an equation for ‘x1’: x1 = f1 $ A "1"
|
27 | > x1 = f1 $ A "1" | ^^^^^^^^^^
这是一个担心,不是很明显吗?......这种事情会再次发生......
如果我写
> f x = bar (foo x)
对我来说这是一件完全合理的事情......ghc同意!
我问它的类型...我明白了
f :: (Bar a1 b, Foo a2 a1) => a2 -> b
我可以买那个。
像一个优秀的程序员一样,我将类型粘贴到
> f :: (Bar a1 b, Foo a2 a1) => a2 -> b
> f x = bar (foo x)
和“砰”的一声……
• Could not deduce (Foo a2 a0) arising from a use of ‘foo’
from the context: (Bar a1 b, Foo a2 a1)
bound by the type signature for:
f :: forall a1 b a2. (Bar a1 b, Foo a2 a1) => a2 -> b
at catdog.lhs:32:3-39
The type variable ‘a0’ is ambiguous
Relevant bindings include
x :: a2 (bound at catdog.lhs:33:5)
f :: a2 -> b (bound at catdog.lhs:33:3)
These potential instance exist:
instance Foo (A a) a -- Defined at catdog.lhs:17:12
• In the first argument of ‘bar’, namely ‘(foo x)’
In the expression: bar (foo x)
In an equation for ‘f’: f x = bar (foo x)
|
33 | > f x = bar (foo x) | ^^^^^
所以 ghc 告诉我它在没有类型声明的情况下推断出的类型,它现在不确定!
现在...我的脑海中通常有一个齿轮通过使用 scala 或 f# 或其他一些 OO 样式类型系统向后转动,我必须反过来...我要疯了吗?
【问题讨论】:
-
我当然不是这方面的专家,但是对于担心#1,我认为正在发生的是,当您省略类型签名时,GHC 看到它需要有一个实例@ 987654328@ 并且无法弄清楚
b是什么。我想在这种情况下它无法看到您的脚本只有一个这样的实例(b是String) - 如果您有多个实例,那么它肯定有理由抱怨歧义。跨度> -
至于第二个,这离我的舒适区更远了,但我猜 GHC 不知道
a1是什么,并且无法阅读约束说“我希望有某种类型的a1约束Bar a1 b和Foo a2 a1同时保持”。不知道你如何设置它(或者如果它可能的话),所以我会把它留给其他更有知识的人。
标签: haskell