在 class 个实例中需要更高种类的类型
Require higher kinded type in class instances
我有一个看起来像这样的类型。
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
我使用类型参数来更改某些字段的类型。这在通过验证管道演进数据结构时很有用。
现在我想写一个 class 可以从这个数据结构中提取一些东西,但它是哪个 State
并不重要。完整示例:
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
class Extractor a where
extract :: a -> (BarTy b)
instance Extractor (Foo a) where
extract (Foo x) = extract x
instance Extractor (Bar a) where
extract (Bar x) = x
这显然是行不通的,因为 b
类型变量在实例中总是未知的,因此会发生类型错误。我可以制作另一个类型族,从给定类型中提取 State
类型,但这对于较大的类型来说确实很笨重。
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
type family ExtractState (t :: Type) :: State where
ExtractState (Foo s) = s
ExtractState (Bar s) = s
ExtractState _ = TypeError ('Text "ExtractState: Passed type is not valid.")
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
class Extractor a where
extract :: a -> (BarTy (ExtractState a))
instance Extractor (Foo a) where
extract (Foo x) = extract x
instance Extractor (Bar a) where
extract (Bar x) = x
bar1 :: Bar 'Unsanitized
bar1 = Bar "Test"
foo1 = Foo bar1
bar2 :: Bar 'Sanitized
bar2 = Bar 1337
foo2 = Foo bar2
a = extract bar1
b = extract foo1
c = extract bar2
d = extract foo2
我最想做的是在 class 声明中进行模式匹配,但我不知道该怎么做,甚至不知道是否可行:
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
class Extractor (t a) where
extract :: (t a) -> (BarTy a)
instance Extractor (Foo a) where
extract (Foo x) = extract x
instance Extractor (Bar a) where
extract (Bar x) = x
可以Haskell做这样的事情吗?还是有其他方法可以实现我想要的?
感谢任何帮助。
请记住,您可以在定义类型类时部分应用类型:
class Extractor t where
extract :: t a -> BarTy a
(在 Functor
、Applicative
、Monad
的定义中使用了相同的技术,并且通常几乎所有类型类都用于更高类型的类型。)
我有一个看起来像这样的类型。
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
我使用类型参数来更改某些字段的类型。这在通过验证管道演进数据结构时很有用。
现在我想写一个 class 可以从这个数据结构中提取一些东西,但它是哪个 State
并不重要。完整示例:
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
class Extractor a where
extract :: a -> (BarTy b)
instance Extractor (Foo a) where
extract (Foo x) = extract x
instance Extractor (Bar a) where
extract (Bar x) = x
这显然是行不通的,因为 b
类型变量在实例中总是未知的,因此会发生类型错误。我可以制作另一个类型族,从给定类型中提取 State
类型,但这对于较大的类型来说确实很笨重。
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
type family ExtractState (t :: Type) :: State where
ExtractState (Foo s) = s
ExtractState (Bar s) = s
ExtractState _ = TypeError ('Text "ExtractState: Passed type is not valid.")
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
class Extractor a where
extract :: a -> (BarTy (ExtractState a))
instance Extractor (Foo a) where
extract (Foo x) = extract x
instance Extractor (Bar a) where
extract (Bar x) = x
bar1 :: Bar 'Unsanitized
bar1 = Bar "Test"
foo1 = Foo bar1
bar2 :: Bar 'Sanitized
bar2 = Bar 1337
foo2 = Foo bar2
a = extract bar1
b = extract foo1
c = extract bar2
d = extract foo2
我最想做的是在 class 声明中进行模式匹配,但我不知道该怎么做,甚至不知道是否可行:
data State = Unsanitized | Sanitized
type family BarTy (s :: State) :: Type where
BarTy 'Unsanitized = String
BarTy 'Sanitized = Int
data Foo (a :: State) = Foo (Bar a)
data Bar (a :: State) = Bar (BarTy a)
class Extractor (t a) where
extract :: (t a) -> (BarTy a)
instance Extractor (Foo a) where
extract (Foo x) = extract x
instance Extractor (Bar a) where
extract (Bar x) = x
可以Haskell做这样的事情吗?还是有其他方法可以实现我想要的?
感谢任何帮助。
请记住,您可以在定义类型类时部分应用类型:
class Extractor t where
extract :: t a -> BarTy a
(在 Functor
、Applicative
、Monad
的定义中使用了相同的技术,并且通常几乎所有类型类都用于更高类型的类型。)