将包含所有操作的自定义 haskell 类型封装到一个 class
Encapsulating a custom haskell type with all operations into one class
如果我想在 C++ 中创建一个新类型,在其中重载一堆运算符,我可以这样做:
class Stringy {
public:
explict Stringy(const char *buffer){}
friend Stringy operator + (const Stringy &s1, const Stringy &s2) { ... }
friend Stringy operator - (const Stringy &s1, const Stringy &s2) { ... }
friend std::ostream& operator << (std::ostream &oss, const String& s1) { ... }
};
现在如果我尝试在 Haskell 中做同样的事情,我发现自己在做(一个例子):
data Stringy = Stringy([Char])
-- do something unrelated here --
(+) :: Stringy -> Stringy -> Stringy
(-) :: Stringy -> Stringy -> Stringy
(removeDups) :: Stringy -> Stringy
-- do something else unrelated here --
(>>) :: Stringy -> IO --(is IO right?)
我的观点是,c++ 看起来更像是组合在一起的,因为你在 class 中所做的一切都以某种方式与 class 相关。另一方面,haskell 的运算符声明可能到处都是,不需要在一起。如果有人看一下 c++ 代码,他们可以立即识别哪些操作是 class 的一部分,哪些不是。我如何在 Haskell 中实现同样的一致性?
我还是Haskell的初学者,所以请用简单的方式做事。谢谢
正如 Daniel 所说,优秀的库设计者确实会尝试将相关功能放入同一个模块中。因此,通常类型类 Stringy
和 Stringy
上的所有 "basic" 操作都将在模块 Stringy
(或 X.Y.Z.Stringy
)中,在文件 Stringy.hs
.
我想您最终会欣赏 Haskell 给您带来的灵活性。
例如,假设您要定义类型为
的函数
myfunction :: Stringy -> Thingy -> Doohicky
这实际上不适合三个类型类(Stringy
、Thingy
或 Doohicky
)中的任何一个,因为它引用了不属于类型类的类型.
也许这三个类型类位于三个不同的模块中,很久以前由不同的人编写。
你是第一个意识到 myFunction
是一个有用的操作的人。
Haskell 允许您将此函数放在您认为最有意义的位置。
您可能会创建一个全新的模块,专门用于从其他类型类的值组合中生成 Doohicky
s 的方法。
如果我想在 C++ 中创建一个新类型,在其中重载一堆运算符,我可以这样做:
class Stringy {
public:
explict Stringy(const char *buffer){}
friend Stringy operator + (const Stringy &s1, const Stringy &s2) { ... }
friend Stringy operator - (const Stringy &s1, const Stringy &s2) { ... }
friend std::ostream& operator << (std::ostream &oss, const String& s1) { ... }
};
现在如果我尝试在 Haskell 中做同样的事情,我发现自己在做(一个例子):
data Stringy = Stringy([Char])
-- do something unrelated here --
(+) :: Stringy -> Stringy -> Stringy
(-) :: Stringy -> Stringy -> Stringy
(removeDups) :: Stringy -> Stringy
-- do something else unrelated here --
(>>) :: Stringy -> IO --(is IO right?)
我的观点是,c++ 看起来更像是组合在一起的,因为你在 class 中所做的一切都以某种方式与 class 相关。另一方面,haskell 的运算符声明可能到处都是,不需要在一起。如果有人看一下 c++ 代码,他们可以立即识别哪些操作是 class 的一部分,哪些不是。我如何在 Haskell 中实现同样的一致性?
我还是Haskell的初学者,所以请用简单的方式做事。谢谢
正如 Daniel 所说,优秀的库设计者确实会尝试将相关功能放入同一个模块中。因此,通常类型类 Stringy
和 Stringy
上的所有 "basic" 操作都将在模块 Stringy
(或 X.Y.Z.Stringy
)中,在文件 Stringy.hs
.
我想您最终会欣赏 Haskell 给您带来的灵活性。 例如,假设您要定义类型为
的函数myfunction :: Stringy -> Thingy -> Doohicky
这实际上不适合三个类型类(Stringy
、Thingy
或 Doohicky
)中的任何一个,因为它引用了不属于类型类的类型.
也许这三个类型类位于三个不同的模块中,很久以前由不同的人编写。
你是第一个意识到 myFunction
是一个有用的操作的人。
Haskell 允许您将此函数放在您认为最有意义的位置。
您可能会创建一个全新的模块,专门用于从其他类型类的值组合中生成 Doohicky
s 的方法。