我想为可减少类型创建一个类型类
Ord.subtract功能.UTCTime,Double和Int(或任选的任何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)
您可以使用类型系列执行此操作:
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)
Intinstance Subtractable Int where
type Diff Int = Int
subtractValues = (-)
Run Code Online (Sandbox Code Playgroud)
MultiParamTypeClasses和FunctionalDependencies你也可以用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的工作,但有可能周围的人可以想出一个技巧(或告诉我我完全错过了这一点;))