如何在Haskell中访问没有记录语法的自定义数据类型的字段?

How to Access Fields of Custom Data Types without Record Syntax in Haskell?

我想了解如何在不使用记录语法的情况下访问自定义数据类型的字段。在LYAH中建议这样做:

-- Example
data Person = Subject String String Int Float String String deriving (Show)  

guy = Subject "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"  

firstName :: Person -> String  
firstName (Subject firstname _ _ _ _ _) = firstname  

我尝试通过获取 BST 节点的值来应用这种访问数据的方式:

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)  

singleton :: a -> Tree a  
singleton x = Node x EmptyTree EmptyTree  
  
treeInsert :: (Ord a) => a -> Tree a -> Tree a  
treeInsert x EmptyTree = singleton x  
treeInsert x (Node a left right)   
    | x == a = Node x left right  
    | x < a  = Node a (treeInsert x left) right  
    | x > a  = Node a left (treeInsert x right) 

getValue :: Tree -> a
getValue (Node a _ _) = a

但是我得到了以下错误:

有人可以解释如何在不使用记录语法的情况下正确访问该字段 and 错误消息的含义是什么?请注意,我是 Haskell 的初学者。我的目的是了解为什么这种特殊情况会引发错误以及如何正确执行。我并不是要将此指向更方便的访问字段的方法(如记录语法)。如果之前有人问过类似的问题:对不起!我真的试着在这里找到答案,但找不到。感谢您的帮助!

您忘记在函数的类型签名中将类型参数添加到 Tree

getValue :: Tree -> a

应该是

getValue :: Tree a -> a

Expecting one more argument to `Tree'

意味着类型签名中的 Tree 需要一个类型参数,但没有提供

Expected a type, but Tree has a kind `* -> *'

Tree a 是一种类型,但 Tree 不是(?)因为它需要一个类型参数。

A kind 就像一个类型的类型签名。 *kind 表示类型构造函数不需要任何类型的参数。

data Tree = EmptyTree | Tree Int Tree Tree

有种*

它就像一个无参数函数的类型签名(我认为从技术上讲这并不是真正的函数)

f :: Tree Int
f = Node 0 EmptyTree EmptyTree

* -> *kind 表示类型构造函数需要一个参数。

您的 Tree 类型有一种 * -> *,因为它采用一个类型参数,即 = 左侧的 a

一种* -> *有点像一个接受一个参数的函数:

f :: Int -> Tree Int
f x = Node x EmptyTree EmptyTree