Haskell 在类实例中需要更高种类的类型

Haskell 在类实例中需要更高种类的类型,haskell,type-families,Haskell,Type Families,我有一种看起来像这样的类型 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) 我使用type参数可以更改某些字段的类型。例

我有一种看起来像这样的类型

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)
我使用type参数可以更改某些字段的类型。例如,当通过验证管道演化数据结构时,这非常有用

现在我想写一个类,它可以从这个数据结构中提取一些东西,但不管它是哪个
状态。完整示例:

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
type变量在实例中总是未知的,因此会发生类型错误。我可以创建另一个类型族,从给定的类型中提取
状态
类型,但对于较大的类型来说,这确实很笨拙

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
理想情况下,我希望在类声明中进行模式匹配,但我不知道如何进行,或者是否可能:

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
哈斯克尔能做这样的事吗?还是有其他方法可以实现我想要的


非常感谢您的帮助。

请记住,在定义typeclass时,您可以部分应用类型:

类提取器t,其中
摘录::t a->BarTy a

(同样的技术在
Functor
Applicative
Monad
的定义中使用,一般来说,任何类型的类都可以用于更高级的类型。)

如果你使用
类提取器t where extract::ta->BarTy a
,那有效吗?@bradrn brilliant!我没想过要试试。它起作用了!请创建一个答案,以便您可以收获您的分数;)我很高兴它在JohnSmith工作!现在回答。