haskell - Haskell 中的函数类型特化

标签 haskell types ghc generic-programming

我有一个类型为Read a => String -> a的函数,是否有可能有另一个同名的函数在a时做不同的事情例如String?是否有任何 GHC 扩展允许这样做?

类似于:

f :: Read a => String -> a
f = read

f :: String -> String
f = id

最佳答案

在 Haskell 中,这种函数重载(即席多态性)是通过使用类型类来完成的,而不是通过在多个类型下绑定(bind)相同的名称来完成。

{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}

class F a where f :: String -> a

instance F String where f = id
instance F Int where f = read
instance F Char where f = read
instance F Float where f = read
-- etc.

现在,f 可以对已声明 F 实例的任何类型进行操作。

不幸的是,您无法摆脱以下问题:

instance Read a => F a where f = read

也许不直观的是,这仅针对具有 Read 实例的类型声明 F 实例。因为 GHC 仅使用实例声明的头部(=> 右侧的部分)来解析实例,这实际上将所有类型 a 声明为 的实例>F,但对任何不是 Read 实例的对象调用 f 会导致类型错误。

如果启用 UndecidableInstances 扩展,它将编译,但这只会导致其他问题。这是一个你不想冒险进入的兔子洞。

相反,您应该为您想要 f 操作的每个单独类型声明一个 F 实例。对于像这样的简单类来说,这并不是很麻烦,但是如果您使用最新版本的 GHC,则可以使用以下命令使其变得稍微容易一些:

{-# LANGUAGE DefaultSignatures #-}

class F a where f :: String -> a
                default f :: Read a => String -> a
                f = read

现在,对于任何 Read 实例的类型,您可以声明其 F 实例,而无需提供 f 的实现> 明确:

instance F Int
instance F Char
instance F Float
-- etc.

对于任何没有 Read 实例的类型,您仍然需要为 f 编写显式实现。

关于haskell - Haskell 中的函数类型特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9881726/

相关文章:

haskell - 如何从 HackageDB 中删除包?

haskell - Haskell 的有限域线性代数库

haskell - Pandoc 在 GHC 7.8.2 上编译失败

haskell - Haskell 适合作为第一语言吗?

Haskell - 无法将类型 `[Char]' 与 `Char' 匹配

haskell - 在 Haskell 中,如何在父进程和 fork 子进程之间共享数据?

haskell - 我可以在 Haskell 中打印多态函数的类型,就像我将一个具体类型的实体传递给它一样吗?

javascript - 在 typescript 中提取给定通用参数的特定联合项

haskell - PolyKinds 的不明确类型

variables - GHC 拒绝 ST monad 代码无法统一类型​​变量?