gpt4 book ai didi

haskell - Haskell 中的函数类型特化

转载 作者:行者123 更新时间:2023-12-02 18:40:00 24 4
gpt4 key购买 nike

我有一个类型为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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com