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

cla*_*lay 2 haskell typeclass

我想为可减少类型创建一个类型类

  • 值类型实现Ord.
  • 有一个subtract功能.
  • 它支持UTCTime,DoubleInt(或任选的任何Num类型)
  • 有一种Delta类型可能与源值类型不同.例如,值类型为UTCTime,delta类型为NominalDiffTime.对于Int,Doubledelta类型与值类型相同.

    diffUTCTime :: UTCTime - > UTCTime - > NominalDiffTime

  • delta类型应该实现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
Run Code Online (Sandbox Code Playgroud)

Car*_*ten 5

您可以使用类型系列执行此操作:

class Subtractable a where
  type Diff a :: *
  subtractValues :: a -> a -> Diff a
Run Code Online (Sandbox Code Playgroud)

在你的例子中,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
Run Code Online (Sandbox Code Playgroud)

并产生这样的东西:

?> t1 <- getCurrentTime
?> t2 <- getCurrentTime
?> subtractValues t2 t1
5.327944s
Run Code Online (Sandbox Code Playgroud)

(你可以看到我打字很慢;))

Num如果添加{-# LANGUAGE FlexibleContexts #-}并更改为class,则可以添加约束:

class (Num (Diff a)) => Subtractable a where
  type Diff a :: *
  subtractValues :: a -> a -> Diff a
Run Code Online (Sandbox Code Playgroud)

实例 Int

instance Subtractable Int where
  type Diff Int = Int
  subtractValues = (-)
Run Code Online (Sandbox Code Playgroud)

使用MultiParamTypeClassesFunctionalDependencies

你也可以用multiparam-type-classes和函数依赖来做这个,但我更喜欢类型族方法 - 但这显然是我的意见

无论如何这里是使用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
Run Code Online (Sandbox Code Playgroud)

备注

  • 只是看到我应该放Delta而不是Diff- 我想你明白了
  • 如果你试图这样做一般Num a你会遇到非常讨厌的东西(编译器将无法决定Diff a基本上选择哪个) - 所以现在我看不到让这个工作ATM的工作,但有可能周围的人可以想出一个技巧(或告诉我我完全错过了这一点;))