Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell特设多态性_Haskell_Polymorphism_Overloading_Typeclass - Fatal编程技术网

Haskell特设多态性

Haskell特设多态性,haskell,polymorphism,overloading,typeclass,Haskell,Polymorphism,Overloading,Typeclass,我试图了解haskell中的特殊多态性,即具有相同的函数为不同的参数类型提供不同的行为 但是当下面的测试代码编译时 {-# LANGUAGE MultiParamTypeClasses #-} class MyClass a b where foo :: a -> b instance MyClass Bool Int where foo True = 0 foo False = 1 instance MyClass Double Double where

我试图了解haskell中的特殊多态性,即具有相同的函数为不同的参数类型提供不同的行为

但是当下面的测试代码编译时

{-# LANGUAGE MultiParamTypeClasses #-}

class MyClass a b where
    foo :: a -> b

instance MyClass Bool Int where
    foo True = 0
    foo False = 1

instance MyClass Double Double where
    foo x = -x
如果我试着用类似

foo True
ghci对我喊道:

No instance for (MyClass Bool b0) arising from a use of `foo'
The type variable `b0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there is a potential instance available:
  instance MyClass Bool Int -- Defined at test.hs:6:10
Possible fix: add an instance declaration for (MyClass Bool b0)
In the expression: foo True
In an equation for `it': it = foo True
但是,如果我指定了返回类型,它将起作用:

foo True :: Int -- gives 0
为什么需要这样做?Bool的参数类型应足以解决歧义


另外:这是实现类似行为的“最佳”方式吗?(没有将函数重命名为
fooBool
foodoull

您面临的问题是,重载由类中的所有类型决定,包括仅显示为返回类型的类型。您可以同时拥有
MyClass Bool Int
MyClass Bool String
的实例,并且可以根据预期的类型消除歧义

Haskell TypeClass的核心设计权衡之一是“开放世界假设”。Haskell类型实例是隐式全局的:特定类型(在本例中为类型序列)在整个程序中只能有一个实例,该实例隐式导出到使用该类型的所有模块

这使得在没有意识到的情况下获取某个类的新实例变得非常容易,因此Haskell typechecker假设实例可能存在于任何有效的类型组合中。在您的例子中,这意味着虽然
MyClass Bool Int
是使用
Bool
的唯一实例,但它与其他可能的
MyClass Bool b
实例仍然不明确

一旦为整个表达式的类型添加注释,它就不再是不明确的,因为
a
b
都是固定的

要获得预期的行为,可以使用。这些允许您指定对于任何给定的
a
,只有一个可能的
b
,这将使GHC正确推断类型。它看起来像这样:

class MyClass a b | a -> b where

当然,这确实有意地抛弃了一些灵活性:现在您不能同时拥有
MyClass Bool Int
MyClass Bool String

Tikhon Jelvis的实例,详细阐述了问题并建议使用函数依赖关系,但还有一种替代方法:。您的代码变为

{-# LANGUAGE TypeFamilies #-}

class MyClass a where
    type R a
    foo :: a -> R a

instance MyClass Bool where
    type R Bool = Int
    foo True  = 0
    foo False = 1

instance MyClass Double where
    type R Double = Double
    foo x = -x

我们在这里使用。我喜欢这些显式类型级别的函数,但如果您不喜欢,可以使用FundeP,因为它们相当微妙。

老实说:我不会从
MultiParamTypeClasses开始,但在您的情况下,您可能也想看看;)(如果不清楚,请按照链接进行操作-问题在这里得到了很好的解释-包括一个可能的解决方案-extenstion说)对于这个任务,我将使用它,而不是函数依赖项。@user3237465将其添加为回答谢谢,这为我澄清了一些事情。但是,即使具有功能依赖性,调用foo 1.73也将失败。你也能解释一下吗?if将失败,因为
1.73
本身不是
Double
,而是更通用的
fractive
——所以你必须执行
foo(1.73::Double)
或修改
foo
实例以获得
分数a
@wonce:这里的问题是
1.73
本身是多态的:它可以是任何
分数
类型,如
浮点
双精度
理性
。因此,在使用哪一个实例时可能会出现歧义。