我有以下类型:
type Name = String
type Assignation a = Name -> a
和以下函数声明:
actAsig :: Assignation a -> Name -> a -> Assignation a
此函数应返回一个新的Assignation
,它返回所提供的Name
新分配的值,以及之前为其他Name
分配的值。
答案 0 :(得分:7)
如果我理解的话,actAsig
的规范是给定的
assignation1 :: Assignation a
newName :: Name
newValue :: a
assignation2 = actAsig assignation1 newName newValue
assignation2
的要求是
assignation2 name = if name == newName then newValue else assignation1 name
所以,你可以这样写出来:
actAsig :: Assignation a -> Name -> a -> Assignation a
actAsig assignation1 newName newValue name =
if name == newName then newValue else assignation1 name
答案 1 :(得分:3)
Cactus已经出色地解决了您对actAsig
函数实现的任何问题,但是,我觉得帖子标题中的问题没有得到解决。
首先,Haskell既有值级语言(Object Language)又有类型级语言(Metalanguage)。它们都很强大,但通常不是同样强大,至少不是同样的事情。但是,有些事情在两面都有效,例如常量,变量和函数。
类型级别常量为:
type Name = String
- 这通常称为“类型别名”:它表示Name
(几乎)所有方面都等同于String
。此不引入新类型,仅为现有类型引入新名称。如果您不想使用data
或newtype
引入实际的新类型,这对于使代码中的意图更具可读性很有用,在这种情况下,您将引入一组新值需要从现有的值集(即类型)映射。因此,type
只是方便,如果您愿意,而不是安全措施,而不是data
和newtype
。
但是,Haskell类型级语言也支持函数,即从1种或更多种类型到某种现有类型的映射。您可以将其视为参数化别名,可以这么说。
type Assignation a = Name -> a
这将创建一个名为Assignation
的类型函数,其参数为a
。给定类型a
,它返回一些类型,在本例中为类型Name -> a
。因此Assignation Int
会返回Name -> Int
; Assignation Person
会返回Name -> Person
,依此类推。请注意,有时类型函数不会使用它们的一个或多个参数,就像值级函数一样:
type Empty a = ()
如果我们结合这些新知识,我们就可以开始考虑类型级别评估/缩减,即仅在类型签名,类型函数,类型类约束计算等边界内进行的评估。
让我们一步一步地将它应用于actAsig
的类型签名:
Assignation a -> Name -> a -> Assignation a
Assignation a -> String -> a -> Assignation a
(Name -> a) -> String -> a -> (Name -> a)
(String -> a) -> String -> a -> (String -> a)
因此,您在上一行中看到的高阶函数类型是actAsig
的实际类型,所有抽象都被消除/减少。
在人类语言术语中,签名描述了一个
的功能f
将字符串映射到某种类型a
的值。a
f
相同类型的新功能。所以在某种程度上,actAsig
处理函数:它接受函数并返回新的,可能已修改的函数。
此外,Haskell还具有(有点基本)模糊类型级别和值级别之间的界限的方法,通过使类型领域中的计算涉及到值级别的引用(依赖性),但这超出了本文的范围,并将引领我们进入Dependent Types和Dependent Type Theory的世界。