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
一个打字机之类的东西。