haskell - 如何实现一个简单的 Subtractable 类型类

标签 haskell typeclass

我想为可减类型创建一个类型类,这样

  • 值类型实现 Ord
  • 有一个函数。
  • 它支持 UTCTimeDoubleInt(或可选的任何 Num 类型)
  • 有一个 Delta 类型,它可能与源值类型不同。例如,对于 UTCTime 值类型,增量类型为 NominalDiffTime。对于IntDouble,增量类型将与值类型相同。

    diffUTCTime::UTCTime -> UTCTime -> NominalDiffTime

  • 增量类型应实现 Num

这根本不起作用,但希望能传达我想要做的事情

class Ord a => Subtractable a where
   -- The type alias for the delta type
   type Num b => b
   -- The subtract function
   subtractValues :: a -> a -> b

最佳答案

您可以使用type families来做到这一点:

class Subtractable a where
  type Diff a :: *
  subtractValues :: a -> a -> Diff a

在您的示例中 UTCTime这将是:

{-# LANGUAGE TypeFamilies #-}
module Stackoverflow where
import Data.Time.Clock

class Subtractable a where
  type Diff a :: *
  subtractValues :: a -> a -> Diff a

instance Subtractable UTCTime where
  type Diff UTCTime = NominalDiffTime
  subtractValues = diffUTCTime

并产生这样的结果:

λ> t1 <- getCurrentTime
λ> t2 <- getCurrentTime
λ> subtractValues t2 t1
5.327944s

(如你所见,我打字速度很慢;))

您可以在Num上添加约束如果添加 {-# LANGUAGE FlexibleContexts #-}并更改 class至:

class (Num (Diff a)) => Subtractable a where
  type Diff a :: *
  subtractValues :: a -> a -> Diff a
<小时/>

Int 的实例

instance Subtractable Int where
  type Diff Int = Int
  subtractValues = (-)
<小时/>

使用MultiParamTypeClassesFunctionalDependencies

您还可以使用 multiparam-type-classes 和 functional dependencies 来做到这一点但我更喜欢类型家庭方法 - 但这显然是我的观点

无论如何,这是一个使用 FD 的版本:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
module StackOverflow where
import Data.Time.Clock

class Num b => Subtractable a b | a -> b where
  subtractValues :: a -> a -> b

instance Subtractable UTCTime NominalDiffTime where
  subtractValues = diffUTCTime
<小时/>

备注

  • 刚刚看到我应该输入 Delta而不是Diff - 我想你明白了
  • 如果您尝试对一般 Num a 执行此操作你会遇到非常讨厌的东西(编译器将无法决定基本上选择哪个 Diff a) - 所以现在我看不出有什么办法可以让这个 ATM 工作,但周围可能有人可以想出一个 < em>诡计(或者告诉我哪里我完全没有捕获要点;))

关于haskell - 如何实现一个简单的 Subtractable 类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35023606/

相关文章:

haskell - 继续单子(monad)实例实现的清晰性

haskell - 实例实现的模式匹配

Haskell - 类型类定义中的类约束

haskell - 为自定义 ZipList 实现 Applicative

haskell - Yesod:通过 ID 从 Int 获取数据库实体

haskell - 使用 randomR 生成奇怪的有偏差随机数

multithreading - 跨线程存储任意函数调用

haskell - 将大型记录类型的解析器提升为仿函数

haskell - Haskell 中的双分类

haskell - 默认方法中对幻像类型的类约束的编译错误