Haskell 中方法的替代方法

问题描述 投票:0回答:1

假设我有以下两个面向对象语言的类:

class List:
  def reverse() -> None:
    ...

class Car:
  def reverse() -> None:
    ...

现在,如果我有

list
的实例
List
car
的实例
Car
,那么当我编写
reverse
list.reverse() 时,我调用哪个 
car.reverse()
 方法绝对没有歧义
。这非常好!

在 Haskell 中,类似的代码类似于:

data List = ...

reverse :: List -> List
reverse = ...

data Car = ...

reverse :: Car -> Car
reverse = ...

有一个迫在眉睫的问题:

reverse
被定义了两次。这个问题并不那么难解决。我们可以定义两个独立的模块
List
Car
,这样两个不同的
reverse
函数就位于不同的命名空间中。然后,如果我有一个类型为
list
的变量
List
和一个类型为
car
的变量
Car
,我可以通过编写
reverse
List.reverse list
来调用相应的
Car.reverse car
函数。这与上一个示例中的代码
list.reverse()
car.reverse()
类似。

最明显的问题是,输入

List.reverse list
而不是
list.reverse()
会更烦人(特别是如果我们用更长的名称替换
List
类型)。 Haskell 中有一些标准方法来处理这个问题吗?请注意,类型类不是这里的解决方案;这两个
reverse
函数具有完全不同的目标。

haskell
1个回答
0
投票

标准的轻量级惯用法是按照您描述的方式使用模块系统。例如,您会经常看到以下内容:

import qualified Data.Vector as V
import qualified Data.Map as M

foo = (V.fromList bar, M.fromList baz)

曾经有一个有点争议的语言扩展提案,称为“类型定向名称解析”,它就位于这个空间中。争议较少(但仍然有些争议)的是现有的“记录字段消歧”语言扩展,但顾名思义,它仅适用于记录字段。 (另请参阅重复记录字段。) 最后,还有类型类机制,我认为你太容易忽略它了。例如,使用 gi-gtk

可以达到良好的效果,并与重载符号结合使用,例如

#foo bar baz
可能会根据

bar
 的类型消除歧义为其中之一:

boxFoo bar baz alertDialogFoo bar baz

对于截然不同的小部件来说,想要表面上相同但具有不同含义、甚至不同数量的方法名称是很常见的,所以这在这里不存在障碍。

	

© www.soinside.com 2019 - 2024. All rights reserved.