学习Purescript,有助于定义类型

学习Purescript,有助于定义类型,purescript,Purescript,我不熟悉函数式编程。我使用了一些Ramda(JavaScript库),但与Purescript中的类型系统不同 我有一个想法,我觉得应该用Purescript的类型系统来表达,但我不确定从哪里开始 假设我正在为数独板定义一些类型 newtype Index=Index Int newtype Column=列Int newtype行=行Int newtype Box=Box Int 我想定义这些类型的加法是什么样子的 在sudocode中: indexAddition::(Index | In

我不熟悉函数式编程。我使用了一些Ramda(JavaScript库),但与Purescript中的类型系统不同

我有一个想法,我觉得应该用Purescript的类型系统来表达,但我不确定从哪里开始

假设我正在为数独板定义一些类型

newtype Index=Index Int
newtype Column=列Int
newtype行=行Int
newtype Box=Box Int
我想定义这些类型的加法是什么样子的

在sudocode中:

indexAddition::(Index | Int)->(Index | Int)->Index
指数相加AB=(a+b)%81
行添加::(行| Int)->(行| Int)->行
行加法a b=(a+b)%9
ColumnAddition和BoxAddition可能会与RowAddition合并,因为它们基本相同

——我必须说a是Int的子集,但Int不是类型类
对所有a。INTA=>a->a->a
fooab=(a+b)%9

不知怎么的,我觉得在这里我可能一开始就走错了路


有什么帮助吗?

要直接回答您的问题,有一种方法可以使函数与不同的类型一起工作,但它们的有限集合(也称为“重载函数”)是类型类。更具体地说,这样的函数应该是一个类型类的方法,然后为希望使用的每个类型(或类型组合)创建一个实例

因此,最直接的方法是:

类索引添加a b,其中
索引添加::a->b->索引
实例addentint::IndexAddition Int其中
索引a b=索引((a+b)%81)
实例AddInIndex::IndexAddition Int Index,其中
索引a(索引b)=索引((a+b)%81)
实例addIndexInt::IndexAddition Index Int其中
索引添加(索引a)b=索引((a+b)%81)
实例addIndexIndex::IndexAddition Index索引,其中
索引添加(索引a)(索引b)=索引((a+b)%81)
如您所见,我创建了四个实例,分别对应于
Index
Int
的每个组合。这是可行的,但不可否认有点复杂。特别是如果添加第三个参数或第三种可能的类型

为了使它更简短、更易于管理,您可能会注意到,为了添加特定类型,您所需要的只是将它们转换为
Int
。如果有,您可以将这两个参数转换为
Int
,然后添加,然后换行为
索引

类是Int a,其中toInt::a->Int
实例ciIndex::IsInt索引,其中toInt(索引a)=a
实例ciInt::IsInt Int,其中toInt a=a
索引加法::对于所有a b。IsInt a=>IsInt b=>a->b->索引
索引添加AB=索引((t输入a+t输入b)%81)


也就是说,我强烈建议你重新考虑你的设计。当然,在任何组合中添加数字和索引的能力乍一看可能看起来整洁漂亮,但在实践中您可能永远不会需要它。即使您在某些非常特殊的情况下这样做,也很容易根据需要包装/展开值。相信我,我去过那里。很多次。

为了直接回答您的问题,使函数能够与不同类型一起工作,但它们的有限集合(也称为“重载函数”)是类型类。更具体地说,这样的函数应该是一个类型类的方法,然后为希望使用的每个类型(或类型组合)创建一个实例

因此,最直接的方法是:

类索引添加a b,其中
索引添加::a->b->索引
实例addentint::IndexAddition Int其中
索引a b=索引((a+b)%81)
实例AddInIndex::IndexAddition Int Index,其中
索引a(索引b)=索引((a+b)%81)
实例addIndexInt::IndexAddition Index Int其中
索引添加(索引a)b=索引((a+b)%81)
实例addIndexIndex::IndexAddition Index索引,其中
索引添加(索引a)(索引b)=索引((a+b)%81)
如您所见,我创建了四个实例,分别对应于
Index
Int
的每个组合。这是可行的,但不可否认有点复杂。特别是如果添加第三个参数或第三种可能的类型

为了使它更简短、更易于管理,您可能会注意到,为了添加特定类型,您所需要的只是将它们转换为
Int
。如果有,您可以将这两个参数转换为
Int
,然后添加,然后换行为
索引

类是Int a,其中toInt::a->Int
实例ciIndex::IsInt索引,其中toInt(索引a)=a
实例ciInt::IsInt Int,其中toInt a=a
索引加法::对于所有a b。IsInt a=>IsInt b=>a->b->索引
索引添加AB=索引((t输入a+t输入b)%81)


也就是说,我强烈建议你重新考虑你的设计。当然,在任何组合中添加数字和索引的能力乍一看可能看起来整洁漂亮,但在实践中您可能永远不会需要它。即使您在某些非常特殊的情况下这样做,也很容易根据需要包装/展开值。相信我,我去过那里。很多时候。

这主要是学术性的,所以它就是这样,但这与描述一个时钟(1pm+3y 1h=2pm)并不遥远。我确实喜欢
类IsInt
可以轻松扩展为行、列和框的实例。让我惊讶的是,这个概念表达得再优雅不过了。谢谢你的回答!这真的很有帮助。不能更优雅地表达的原因恰恰是,这通常不是最好的方式。即使在您的示例中,在描述时钟时,签名也是
add::Time->Duration->Time
。没有不同的类型。啊,很公平!再次感谢您的帮助这主要是学术性的,所以它是什么,但