Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在类型级别的函数上进行模式匹配是可能的,但在值级别上不可能,为什么会有这种差异?_Haskell_Type Families_Higher Order Types - Fatal编程技术网

Haskell 在类型级别的函数上进行模式匹配是可能的,但在值级别上不可能,为什么会有这种差异?

Haskell 在类型级别的函数上进行模式匹配是可能的,但在值级别上不可能,为什么会有这种差异?,haskell,type-families,higher-order-types,Haskell,Type Families,Higher Order Types,SPJ在第3页和第4页的论文中写道: class Mutation m where type Ref m :: * -> * newRef :: a -> m (Ref m a) readRef :: Ref m a -> m a writeRef :: Ref m a -> a -> m () instance Mutation IO where type Ref IO = IORef newRef = newIORef readRe

SPJ在第3页和第4页的论文中写道:

class Mutation m where
  type Ref m :: * -> *
  newRef :: a -> m (Ref m a)
  readRef :: Ref m a -> m a
  writeRef :: Ref m a -> a -> m ()

instance Mutation IO where
  type Ref IO = IORef
  newRef = newIORef
  readRef = readIORef
  writeRef = writeIORef

instance Mutation (ST s) where
  type Ref (ST s) = STRef s
  newRef = newSTRef
  readRef = readSTRef
  writeRef = writeSTRef
以及:

类声明现在引入了一个类型函数Ref(带有 指定种类)以及常用的值函数,如newRef (每个都具有指定的类型)。同样,每个实例声明 在实例类型中提供一个定义类型函数的子句 旁边是每个值函数的见证

我们说Ref是一种类型 家族,或类突变的相关类型。它的行为就像一个 函数位于类型级别,因此我们也将Ref称为类型函数。 应用类型函数使用与应用类型相同的语法 构造函数:上面的Ref m a表示将类型函数Ref应用于m, 然后将生成的类型构造函数应用于

那么换句话说,

Ref::(*->*)->*->*

也就是说,
Ref
将类型级函数作为参数,例如
可能
IO
[]
,并使用模式匹配生成另一个类型级函数,例如
IORef
,即
Ref
模式匹配定义

那么,如何可能在类型级别的函数上进行模式匹配,而在值级别上不进行模式匹配呢

比如说,

fun2int:: (Int->Int)->Int
fun2int (+)=2
fun2int (*)=3
无法写入,因为函数上的相等是不可能的

1) 那么,在类型级别上,这怎么可能没有问题呢

2) 是不是因为类型级别上的函数种类非常有限?因此,类型级别上没有任何类型的函数可以成为
Ref
的参数,只有少数几个,即程序员声明的函数,而不是像(+)这样的函数,它们比程序员声明的函数更通用?这就是为什么在类型级别上函数模式匹配不会导致问题的原因吗


3) 这个问题的答案是否与GHC规范的一部分有关?

简单地说,类型级别的函数值没有模式匹配,只有名称匹配

与许多其他语言一样,在Haskell中,类型按名称分开,即使它们的表示形式相同

data A x = A Int x
data B x = B Int x
上面,
A
B
是两个不同的类型构造函数,即使它们描述了相同的类型级函数:在伪代码
\x->(Int,x)
中,大致相同。 在某种意义上,这两个相同的类型级别函数具有不同的名称/标识

这与

type C x = (Int, x)
type D x = (Int, x)
它们都描述了与上面相同的类型级别函数,但没有引入两个新的类型名。以上只是同义词:它们表示一个函数,但没有自己独特的标识

这就是为什么可以为
ax
bx
添加类实例,但不能为
cx
dx
添加类实例的原因:尝试添加后一个实例会将实例添加到类型
(Int,x)
,而将实例与类型名
(,)
Int
关联

在价值层面上,情况并没有太大不同。实际上,这里有值构造函数,它们是具有名称/标识的特殊函数,以及没有实际标识的正则函数。我们可以根据一个由构造函数构建的模式进行模式匹配,但不能与任何其他模式进行匹配

case expOfTypeA   of A n t -> ... -- ok
case someFunction of succ -> ...  -- no
请注意,在类型级别,我们无法轻松地进行模式匹配。Haskell只允许利用类型类来实现这一点。这样做是为了保留一些理论属性(参数性),并允许有效的实现(允许类型擦除——我们不必在运行时用其类型标记每个值)。这些特性的代价是限制类型级模式匹配到类型类——这确实给程序员带来了一些负担,但好处大于缺点

{-# LANGUAGE TypeFamilies, DataKinds, PolyKinds #-}
import GHC.TypeLits
让我们在Haskell中的类型和值级别之间画一些相似之处

首先,我们在类型和值级别都有不受限制的功能。在类型级别,可以使用类型族表达几乎任何内容。不能在类型或值级别的任意函数上进行模式匹配。你不能说

type family F (a :: *) :: *
type family IsF  (f :: * -> *) :: Bool where
  IsF F = True
  IsF notF = False

-- Illegal type synonym family application in instance: F
-- In the equations for closed type family ‘IsF’
-- In the type family declaration for ‘IsF’
Second,我们已经完全应用了数据和类型构造函数,例如值级别上的
Just 5::Maybe Integer
,或者类型级别上的
Just 5::Maybe Nat

可以在以下各项上进行模式匹配:

isJust5 :: Maybe Integer -> Bool
isJust5 (Just 5) = True
isJust5 _ = False

type family IsJust5 (x :: Maybe Nat) :: Bool where
  IsJust5 (Just 5) = True
  IsJust5 x = False
请注意任意函数和类型/数据构造函数之间的区别。构造函数的属性有时称为生成性。对于两种不同的函数
f
g
,对于某些
x
,很可能
fx=gx
。另一方面,对于构造函数,
fx=gx
意味着
f=g
。这种差异使得第一种情况(任意函数上的模式匹配)不可判定,而第二种情况(完全应用的构造函数上的模式匹配)可判定且易于处理

到目前为止,我们已经看到了类型和值级别的一致性

最后,我们已经部分应用了(包括未应用的)构造函数。在类型级别上,包括
可能
IO
[]
(未应用)以及
字符串
(,)Int
(部分应用)。在值级别上,我们只应用了
,部分应用了
(,)5
(:)True

生成性条件不关心应用程序是否已满;因此,对于部分应用的构造函数,没有什么可以排除模式匹配。这就是你在类型层面上看到的;我们也可以在价值层面上拥有它

type family IsLeft (x :: k -> k1) :: Bool where
  IsLeft Left = True
  IsLeft x = False

isLeft :: (a -> Either a b) -> Bool
isLeft Left = True
isLeft _ = False
-- Constructor ‘Left’ should have 1 argument, but has been given none
-- In the pattern: Left
-- In an equation for ‘isLeft’: isLeft Left = True
不支持这一点的原因是效率。类型级的计算 在编译时以解释模式执行;所以我们