Haskell构造函数别名

Ben*_*Ben 5 haskell pattern-synonyms

有没有办法在Haskell中创建相当于创建"构造函数别名"的东西?我认为类似于别名,你可以给类型一个不同的名称,但它仍然以各种方式表现为别名类型.

我的用例是一个系统,我将指定的时间作为我正在建模的某些对象的属性,所以UTCTime.其中一些可能是"可变"时间,这意味着它可能尚未分配时间或它所具有的时间是"可移动的".所以Maybe UTCTime.

但只有部分对象具有可变时间.其他人有固定的时间,系统必须作为一个常数; 当前分配给特定时间的时间变量的处理方式与固定时间不同.现在暗示Either UTCTime (Maybe UTCTime); 它可以是固定时间,也可以是未分配的可变时间.

通用类型似乎非常适合我正在尝试建模的东西,所以使用它们感觉很自然.不过,虽然这是什么明显Either UTCTime (Maybe UTCTime) ,这不是特别明显这是什么意思,所以一些描述性的特殊情况下的名字就好了.

一个简单的type Timeslot = Either UTCTime (Maybe UTCTime)肯定会清理我的类型签名很多,但这对构造函数没有任何作用.我可以使用类似的东西bound = Just来获取构造值的名称,但不能用于模式匹配.

在另一端,我可以用我想要的任何名称定义一个自定义ADT,但后来我失去了EitherMaybe类型的所有预定义功能.或者更确切地说,我将一直来回应用变换(我认为这并不比使用newtype包装器的情况更糟,只是没有效率保证,但我怀疑这无论如何都会成为瓶颈).我想要理解使用泛型EitherMaybe函数操作我的Timeslot值的代码我需要知道标准构造函数映射到我想要使用的任何方式的方式,转换函数将提供一个方便的编译器强制定义的映射.所以也许这是一个很好的方法.

我很确定我知道Haskell很好地说没有构造函数别名这样的东西,但我很好奇是否有一些我不知道的hack,或者其他一些处理这种情况的好方法.

Dan*_*ner 18

尽管你提到了一些缺点,但我强烈建议你为你的类型创建一个新的ADT; 例如

data TimeVariable = Constant UTCTime | Assigned UTCTime | Unassigned
Run Code Online (Sandbox Code Playgroud)

我提出这些论点:

  1. 拥有描述性构造函数将使您的代码(构造和模式匹配)更具可读性.比较UnassignedRight Nothing.现在添加六个月并进行相同的比较.
  2. 我怀疑随着应用程序的增长,你会发现这种类型需要扩展.使用自定义ADT可以更轻松地向现有构造函数添加另一个构造函数或其他字段,并且可以非常轻松地识别需要更新以处理新类型的代码位置.
  3. 可能在这种类型上没有那么多合理的操作,就像标准库中的munging EitherMaybe值一样 - 所以我敢打赌你不会像你想象的那样复制几乎相同数量的代码.虽然您可能正在复制某些代码,但为您的构造函数描述性名称提供相同的可读性和重构原因,为您的函数提供描述性名称是有价值的.
  4. 我亲自写了一些代码,其中我的所有款项Either和我的所有产品都是(,).那太差了.我永远无法记住一笔钱的哪一面意味着哪一件事; 在阅读旧代码时,我不得不经常提醒自己每个值应该是什么样的概念类型(例如Right,不告诉你是否在Right这里使用时间变量的一部分或者是你懒得的其他事情的一部分做一个ADT); 我不得不在精神上扩展类型别名; 从我的痛苦中学习.;-)


aav*_*ogt 4

“模式同义词”可能会合并到 ghc 中:http ://ghc.haskell.org/trac/ghc/ticket/5144 。同时还有 -XViewPatterns,它可以让您编写如下内容:

type Timeslot = Either UTCTime (Maybe UTCTime)
fieldA = either Just (const Nothing)
fieldB = either (const Nothing) id


f (fieldA -> Just time) = ...
f (fieldB -> Just time) = ...
f _ = ...
Run Code Online (Sandbox Code Playgroud)