在Haskell函数中返回类的实例

and*_*gps 5 haskell return instance

如果函数的返回是a class ClassA,是否可以在这样的函数中返回任何实例ClassA?例如:someFunction :: (ClassA a) => String -> a

那么,为什么下面的这个功能不起作用?请注意,这String是一个实例Eq

getAnyEq :: (Eq a) => String -> a
getAnyEq input  |input == "1" = "something"
                |otherwise = "other"
Run Code Online (Sandbox Code Playgroud)

发生的错误是:

Could not deduce (a ~ [Char])
from the context (Eq a)
  bound by the type signature for getAnyEq :: Eq a => String -> a
  at src/InterceptorRegistry.hs:11:13-33
  `a' is a rigid type variable bound by
      the type signature for getAnyEq :: Eq a => String -> a
      at src/InterceptorRegistry.hs:11:13
Run Code Online (Sandbox Code Playgroud)

我试图在互联网资源上找到这个确切的解释,但我没有找到......你能告诉我一些吗?

Dav*_*ani 11

该类型Eq a => a并不意味着"实现的类型Eq",而是"任何实现的类型Eq.例如,如果使用undefined实现您的函数:

getAnyEq :: (Eq a) => String -> a
getAnyEq str = undefined
Run Code Online (Sandbox Code Playgroud)

以下函数正确编译(尽管在运行时会因未定义的错误而崩溃):

x,y,z :: Bool
x = getAnyEq "test" == "hello"
y = getAnyEq "test" == [Just (Right True)]
z = getAnyEq "test" == ("this", "sss")
Run Code Online (Sandbox Code Playgroud)

由于无法为结果生成值,因此无法对函数进行合理的实现.

只有当类型变量具有包含返回值的函数的类的实例时,才返回类型变量的函数才有意义.例如考虑Num类:

class (Eq a, Show a) => Num a where
  (+) :: a -> a -> a
  (*) :: a -> a -> a
  (-) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
Run Code Online (Sandbox Code Playgroud)

(注意我在ghc的旧版本上测试了这个,你的Num可能没有Eq或Show约束).

该函数fromInteger返回a(不需要a输入),因此我们可以a从该类型类中获取.有值后,可以使用其他功能.所以以下功能有效:

getANum:: (Num a) => String -> a
getANum "zero" = fromInteger 0
getANum "asdf" = fromInteger 46
getANum _ = fromInteger 1

> getANum "asdf"
46
Run Code Online (Sandbox Code Playgroud)

请注意,由于文字整数被有效地解析为fromInteger <num>,fromInteger因此上述函数中的函数调用实际上不是必需的.我只是将它们包括在内以展示它的工作原理.

可用于检索值的其他常见类型类是:

  • Monad(使用return)
  • Applicative(使用pure)
  • Monoid(使用mempty)
  • Read(使用read或其他任何其他功能)