Haskell 类型类中的类型变量

Haskell 类型类中的类型变量,haskell,generics,types,automata,Haskell,Generics,Types,Automata,我有一个关于类型类的奇怪问题。因此,您可以定义如下所示的基本类型类: class Property x where checkThing :: x -> Int -> Bool transformThing :: x -> x class Automata machine where isDeterministic :: machine -> Bool acceptsInput :: machine -> String ->

我有一个关于类型类的奇怪问题。因此,您可以定义如下所示的基本类型类:

class Property x where
    checkThing :: x -> Int -> Bool
    transformThing :: x -> x
class Automata machine where
    isDeterministic :: machine -> Bool
    acceptsInput :: machine -> String -> Bool
如果希望具有具有多个参数的类型类,可以启用:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
这将允许您执行以下操作:

class Property x y where
    checkThing :: x -> Int -> Bool
    transformThing :: x -> y -> Int
这是我的问题:假设我想为自动机(接受一种语言的类型)编写一个类型类。我将编写一个类型类,其外观如下:

class Property x where
    checkThing :: x -> Int -> Bool
    transformThing :: x -> x
class Automata machine where
    isDeterministic :: machine -> Bool
    acceptsInput :: machine -> String -> Bool
自动机接收输入并决定该输入是否是语言的一部分。上面的课程将适用于此。但是等等,这仅限于字符(字符串)列表,如果我想用自动机来概括呢?我可以在我的类定义中添加另一个变量:

class Automata machine alphabet where
    isDeterministic :: machine -> Bool
    acceptsInput :: machine -> [alphabet] -> Bool
嗯,没关系。但字母表可能和机器并没有直接关系。不过我很幸运!我可以启用:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
并迫使语言依赖于机器

class Automata machine alphabet | machine -> alphabet where
好的,现在当我做一个自动机的实例时,我可以要求字母表与机器相关。例如:

instance Automata (FSM alphabet) alphabet where
有效,这是正确的

instance Automata (FSM alphabet) othertypevariable where
给出了一个错误。这是可以的,但不是很一般。例如,我必须为每种类型的自动机定义一个实例,以及它们可以采用的每种类型的字母表。那太可怕了。此外,函数依赖关系实际上并不强制建立关系。你可以写:

 instance Automata (FSM alphabet) Int where
没有编译器错误。这是理想的情况

class Automata (machine alphabet) where
    isDeterministic :: machine alphabet -> Bool
    acceptsInput :: machine alphabet -> [alphabet] -> Bool
如果我可以在正在为其定义的数据实例上指定特定的类型参数。例如,可以为automata定义的数据如下所示:

data FSM alphabet = FSM [alphabet]
或者类似的。这还允许定义单个通用实例,例如:

instance Automata (FSM alphabet) where

这些例子是我试图做的一个简化版本,但这个问题的解决方案可以解决我的问题。我怎么能这样表达呢?我能随心所欲地学习打字吗?语言扩展是可以接受的。

Haskell类型的类可以对任意类型进行抽象。这意味着o类型类的参数本身可以有参数。常见的例子包括
函子
单子
,它们接受像
[]
可能
这样的参数。下面是一种使用
*→*种类:

class Automata machine where
    isDeterministic :: machine alphabet -> Bool
    acceptsInput :: machine alphabet -> [alphabet] -> Bool

data FSM alphabet = FSM [alphabet] -- just an example, you need more 
                                   -- stuff to define a real FSM...

instance Automata FSM where 
    ...
使用
{-#LANGUAGE KindSignatures}
可以明确显示
机器的类型:

class Automata (machine :: * -> *) where

Haskell类型的类可以抽象任意类型。这意味着o类型类的参数本身可以有参数。常见的例子包括
函子
单子
,它们接受像
[]
可能
这样的参数。下面是一种使用
*→*种类:

class Automata machine where
    isDeterministic :: machine alphabet -> Bool
    acceptsInput :: machine alphabet -> [alphabet] -> Bool

data FSM alphabet = FSM [alphabet] -- just an example, you need more 
                                   -- stuff to define a real FSM...

instance Automata FSM where 
    ...
使用
{-#LANGUAGE KindSignatures}
可以明确显示
机器的类型:

class Automata (machine :: * -> *) where

也许你的意思是类可以抽象任意类型,这是对具体类型的正确衬托。类型构造函数是任意类型级别术语的陪衬。e、 g.
Bool
可能
、和
状态
都是类型构造函数,但是
状态s
——虽然它不是一个具体的类型,并且具有更高的种类——却不是一个类型构造函数。@DanielWagner您可以称它为类型构造函数表达式。见(pdf)。但也许你是对的,这是一个过时的术语。也许你的意思是类可以抽象任意类型,这是对具体类型的正确衬托。类型构造函数是任意类型级别术语的陪衬。e、 g.
Bool
可能
、和
状态
都是类型构造函数,但是
状态s
——虽然它不是一个具体的类型,并且具有更高的种类——却不是一个类型构造函数。@DanielWagner您可以称它为类型构造函数表达式。见(pdf)。但也许你是对的,这是一个过时的术语。n.m.的答案是正确的,但你不满意函数依赖方法的原因对我来说没有意义。n.m.的答案是正确的,但你不满意函数依赖方法的原因对我来说没有意义。