Haskell:我如何设置多态类型的参数和返回类型

时间:2018-04-02 06:47:37

标签: haskell

我想在多态类型的参数和返回类型中定义一组函数,如下所示。

class Poly a b where
  poly :: a -> b

instance Poly Int Int where
  poly :: Int -> Int
  poly a = a

当我在ghci中测试它时,使用poly 3 :: Int然后它会给我错误:

*Poly> poly 3 :: Int

<interactive>:486:1: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘poly’
      prevents the constraint ‘(Poly a0 Int)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instance exist:
        instance Poly Int Int
          -- Defined at OneFunctionManyArguments.hs:10:10
    • In the expression: poly 3 :: Int
      In an equation for ‘it’: it = poly 3 :: Int

<interactive>:486:6: error:
    • Ambiguous type variable ‘a0’ arising from the literal ‘3’
      prevents the constraint ‘(Num a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance Num Integer -- Defined in ‘GHC.Num’
        instance Num Double -- Defined in ‘GHC.Float’
        instance Num Float -- Defined in ‘GHC.Float’
        ...plus two others
        ...plus 46 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘poly’, namely ‘3’
      In the expression: poly 3 :: Int
      In an equation for ‘it’: it = poly 3 :: Int

当我使用poly (3 :: Int) :: Int时,它会返回正确的值3 ... 我想知道如何摆脱繁琐的:: Int声明?

1 个答案:

答案 0 :(得分:5)

更改poly的类型?现在没有什么能阻止你(或一些随机库)添加例如Poly Double Int实例,这就是3poly 3的类型不明确的原因。

你可以做到

instance Poly a where
    poly :: a -> a

这会确定poly 3 :: Int的类型,但会使poly不那么笼统。

您可以启用FunctionalDependencies并执行

instance Poly a b | b -> a where
    poly :: a -> b

然后poly 3 :: Int就行了,因为b被声明为唯一确定a

您还可以启用TypeFamilies并使用关联的类型:

class Poly b where
    type Arg b :: *
    poly :: Arg b -> b

instance Poly Int where
    type Arg Int = Int
    poly x = x

同样,这允许ghc从结果类型派生参数类型,因此poly 3 :: Int typechecks。