在Haskell中创建泛型函数类型的集合是否有用

这是关于
Haskell风格的问题.

作为教程示例,我创建了一个支持撤消和重做操作的小程序.它使用具有两个堆栈的数据结构.

data History a = History [a] [a]

第一个堆栈是比赛的历史.第二个堆栈存储由撤消弹出的状态.所以

undo (History (x:xs) redoStack) = History xs (x:redoStack)
undo history = history -- in case there is nothing to undo

redo (History hStack (x:redoStack)) = History (x:hStack) redoStack 
redo history = history -- in case there is nothing to redo

还有一个通用操作将更改应用于当前状态.

applyAChange change (History (x:xs) _) = History ((change x):x:xs) []

applyAChange的类型是

applyAChange :: (a -> a) -> History a -> History a

我决定定义一个Change类型:

type Change a = a -> a

然后applyAChange的类型变为

applyAChange :: Change a -> Change (History a)

这似乎很有用,我在代码中的其他地方使用了Change类型.

在定义String实例时,我发现自己定义了许多类型的函数,例如:

convertASomethingToString :: Something -> String

所以我定义了一个ToString类型

type ToString a = a -> String

这允许我用类型编写前面的函数

convertASomethingToString :: ToString <Something>

所有这一切似乎都很好,使代码更具信息性.我的问题是

>这种事情有多少值得做?
>只要有人这样做,创建一个由这些类型定义组成的模块并导入它是否有意义?这是标准的事情吗?
>是否已经有一个广泛使用的这类有用类型的模块?

谢谢.

最佳答案 如前所述,您可以使用Endo从Data.Monoid而不是您的Change类型别名中使用newtype.有时处理包装/展开可能是不方便的.但是如果你想要可组合的更改,你可以在它的Monoid实例中找到有用的东西.

关于您的历史数据类型:它是Haskell世界中众所周知的ListZipper.你可以在不同的地方阅读这个概念.但是在您的代码中,您已经可以在hackage上使用现有的包:http://hackage.haskell.org/package/ListZipper

它有您的功能和其他一些您可能会发现有用的功能.

ToString类型别名基本上是一种没有Show约束的show函数.我不知道如何在没有显示类型绑定的情况下将泛型转换为String,但是如果不查看代码我就不能说更多.所以,我的观点是,你基本上不需要ToString类型的别名.最好使用标准函数和类型类.

点赞