Haskell类依赖项
以下代码未编译:Haskell类依赖项,haskell,typeclass,Haskell,Typeclass,以下代码未编译: class Foo f where getInt :: f -> Int class Bar b where getFooFromBar :: Foo f => b -> f someFunction :: Bar b => b -> Int someFunction bar = getInt $ getFooFromBar bar 错误是无法从上下文(b栏)中推断出使用“getInt”时产生的(Foo f) 我知道我可以通过如下更改
class Foo f where
getInt :: f -> Int
class Bar b where
getFooFromBar :: Foo f => b -> f
someFunction :: Bar b => b -> Int
someFunction bar = getInt $ getFooFromBar bar
错误是无法从上下文(b栏)中推断出使用“getInt”时产生的(Foo f)
我知道我可以通过如下更改Bar
的类来修复错误:
class Foo f => Bar f b where
getFooFromBar :: b -> f
但是如果我不必将f
添加到Bar
的所有实例签名中,我会更愿意这样做
是否有一种方法可以做到这一点,即只对getFooFromBar
签名而不是整个类保留Foo f
约束
但是如果我不必将f
添加到Bar
的所有实例签名中,我会更愿意这样做
从技术上讲,您不需要这样做来编译示例。您可以使用类型注释来指定在someFunction
中使用的Foo
的哪个实例,从而解决不明确的类型变量错误。但是,您有一个更深层次的问题:
class Foo f where
getInt :: f -> Int
class Bar b where
getFooFromBar :: Foo f => b -> f
就所有实际目的而言,这是不可能的。getFooFromBar
的类型表示您可以使用它生成具有Foo
实例的任何类型的f
的结果。但是,对于任何f
,您将如何实现该值?在定义getFooFromBar
时,访问任何特定实例都是没有用的,因为您将从中得到的只是一个无法将类型“f”与“Blah”匹配的类型错误。出于另一个原因,您在问题中建议的解决方案是:通过Bar
实例指定要使用的Foo
实例。您可能会发现使用类型族比使用多参数类型类更好:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
class Foo f where
getInt :: f -> Int
class Foo (FooBar b) => Bar b where
type FooBar b :: *
getFooFromBar :: b -> FooBar b
instance Foo Char where
getInt = const 99
instance Bar Char where
type FooBar Char = Char
getFooFromBar = const 'a'
someFunction :: Bar b => b -> Int
someFunction = getInt . getFooFromBar
我建议您重新考虑getFooFromBar
的类型-它看起来似乎有一个不明确的类型变量
错误。@Alec完整的错误确实表明类型变量“f0”不明确
。可能重复
GHCi> someFunction 'z'
99