Haskell新类型定义
我在为家庭作业提供的代码中读到了这句话:-Haskell新类型定义,haskell,newtype,Haskell,Newtype,我在为家庭作业提供的代码中读到了这句话:- newtype STR a = STR (Store -> (Result a, Store)) 上面的链接使它看起来像: a === (Store -> (Result a, Store)) 这怎么可能是一个有效的声明?这是否意味着a是一个函数,它将Store作为参数并返回(“结果中包装的相同函数”,Store)?newtype定义有点混乱,因为符号STR有两种不同的含义:即类型名称的含义(第一次出现)和构造函数(第二个)。将两者重命
newtype STR a = STR (Store -> (Result a, Store))
上面的链接使它看起来像:
a === (Store -> (Result a, Store))
这怎么可能是一个有效的声明?这是否意味着
a
是一个函数,它将Store作为参数并返回(“结果中包装的相同函数”,Store)
?newtype
定义有点混乱,因为符号STR
有两种不同的含义:即类型名称的含义(第一次出现)和构造函数(第二个)。将两者重命名为不同的名称将导致相同的结果
newtype STRType a = STRConstructor (Store -> (Result a, Store))
换句话说,这引入了一个类型STRType a
,它在结构上与Store->(结果a,Store)
(但需要包装在STRConstructor
中)
我希望你的课程/书已经探讨了
类型
、数据
和新类型
之间的区别;否则,我担心这会变得相当神秘……因此对于数据/新类型定义,左手边有一个类型定义,包括名称和一些类型变量,而右手边有一个构造函数列表,通常也包括名称和类型。例如:
data List x = Nil | Cons x (List x)
请注意,Nil
和Cons
是您的构造函数,x
和List x
是Cons
构造函数的参数类型,而List
是类型的名称(具有种类*->*
;它需要一个类型参数来“填充”,然后才能描述一个类型参数列表)
有时我们想给一个类型加别名。有两种方法可以做到这一点。首先,type
,这使类型保持一致——因此,如果您编写type DirectoryPath=[String]
,那么当您有一个DirectoryPath
时,您可以像处理字符串列表一样对其进行操作;特别是,您可以使用:
或++
附加到它;所以“apps”:基本目录完全合法
有时,您只想用一个大的警告标志来结束这些函数,“如果您不知道自己在做什么,请不要使用它。”为此,您可以编写data FilePath=FilePath[String]
。请注意,我们有点滥用符号,将该类型命名为该类型的唯一构造函数。现在要做同样的事情,你必须写:
case base_directory of FilePath bd -> FilePath $ "apps" : bd
你为什么要这样做?首先,在上面的语法中,目录结构从右向左增长,而大多数人从左向右写目录。其次,您可能希望附加一个
作为no op(即bd++[]
),而.
作为父指针(即尾bd
)。您可能还需要维护一些奇怪的约定(例如,如果列表以“”开头,则它是绝对目录,否则它是相对于当前目录的)。最后,您可能希望稍后将代码转换为Maybe[String]
,以便Nothing
值可以表示执行疯狂操作的路径,例如/../..
(根上的两个父级的绝对路径)
如果您只需说:
FilePath xs ./ x
| x == "." = FilePath xs
| x == ".." = FilePath (tail xs)
| otherwise = ...
然后强制其他地方的人编写base\u目录。/“apps”
另一个例子是newtype SanitizedString=Sanitized String
。因为我们没有使用类型
,所以我们得到了一个编译时标签,它可以跟踪代码,确保用户提供的字符串在进入数据库insert语句或用户界面或其他任何地方之前正确转义
您可能在这里使用它的目的是,您可以为该类型编写一个Monad
实例,从而将其与do
-符号一起使用
如果您的代码只包装一个现有类型,newtype
可以避免引入额外的惰性担忧和数据构造函数延迟等。否则它就像数据
。因此,在您的代码中:
newtype STR a = STR (Store -> (Result a, Store))
这不是类型
同义词,更像是编译后最终消失的数据
构造函数。STR A
是Store->(Result A,Store)
的别名,它被包装在STR
构造函数中(因此它不能在没有解构赋值的情况下直接用作函数)。什么是“正常对象模型语义”的意思?我同意“正常”是一个有争议的词。但我找不到更好的方式来表达我的困惑。我的观点是,尝试用简单的语言来表达你的观点要比使用像“对象模型语义”这样的花哨词汇要好得多。Haskell甚至没有对象,因此这样的描述更容易混淆,而不是进行通信。我可以建议使用术语“类型构造函数”和“数据构造函数”吗?我实际上更喜欢消除“构造函数”一词的过载,让构造函数在值级别上工作(即,它们在运行时“在堆上”执行某些操作),然后调用STRType
一个打字机之类的东西。