不在范围内:数据构造函数`Song' - Haskell

Kan*_*tin 1 database constructor haskell types scope

type Song = (String, String, Int) --(title, artist, sales)

database :: [Song]
database = [("Amon Amarth","Ravens flight", 1), 
  ("Amon Amarth","Shield wall", 11),
  ("Amon Amarth","The way of vikings", 105),
  ("Elijah Nang","Journey to the west", 1000),
  ("Elijah Nang","Tea house", 7),
  ("Pink Floyd","Wish you were here", 123),
  ("Amon Amarth","Raise your horns", 9001),
  ("NLE Choppa","Walk 'em down'", 69420),
  ("Elijah Nang","Kumite", 1337),
  ("NLE Choppa","Shotta flow 6", 511),
  ("Pink Floyd","Comfortably numb", 9),
  ("Pink Floyd","Shotta flow 6", 711), -- changed to match the name of an nle choppa song as requested
  ("Johannes Chrysostomus Wolfgangus Theophilus Mozart","Requiem", 10203948),
  ("Elijah Nang","Kenjutsu water style", 1),
  ("NLE Choppa","Shotta flow 5", 1),
  ("Pink Floyd","High hopes", 1),
  ("Amon Amarth","Deceiver of the gods", 1),
  ("Johannes Chrysostomus Wolfgangus Theophilus Mozart","Turkish march", 1),
  ("Chance The Rapper","Cocoa butter kisses", 1),
  ("Chance The Rapper","Favourite song", 1),
  ("Chance The Rapper","Hot shower", 1),
  ("Chance The Rapper","High hopes", 1)] 


getTrackSale :: Int -> String -> String -> String --(index, artist, track, sales)
getTrackSale index artist track
  | ((getArtist(database!!index) == artist) && (getTrack(database!!index) == track)) = getTrackSale(database!!index)
  | otherwise = getTrackSale(index + 1 artist track)


task2 = getTrackSale(0 "Chance The Rapper" "Hot Shower")

getArtist :: Song -> String
getArtist (Song y _ _) = y

getTrack :: Song -> String
getTrack (Song _ z _) = z

getSale :: Song -> Int
getSale (Song _ _ x) = x
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚这意味着什么或如何解决它,我之前已经为三个“get”函数编写了相同的函数并且它们没有问题,但是我之前确实使用过“type”声明,所以我想就是这样。我有使用相同类型声明的示例代码,它工作正常,所以我在这里有点迷失。

dfe*_*uer 5

你写

type Song = (String, String, Int)
Run Code Online (Sandbox Code Playgroud)

这意味着Song是一种类型的同义词(String, String, Int)。也就是说, aSong实际上只是一个有序三元组,使用有序三元组构造函数构造(,,)。但后来你写

type Song = (String, String, Int)
Run Code Online (Sandbox Code Playgroud)

(不存在的)Song数据构造函数上的模式匹配。

你可以通过写来坚持类型同义词

getArtist :: Song -> String
getArtist (y, _, _) = y
Run Code Online (Sandbox Code Playgroud)

等等。或者您可以创建Song自己的数据类型:

data Song = Song
  { getArtist :: String
  , getTrack :: String
  , getSale :: Int }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您必须修改database定义才能使用Song构造函数。使用自定义数据类型声明更惯用,更能自我记录,它使 Haskell 的类型系统做更多的工作来帮助您发现代码中的错误。作为一般规则,我建议 Haskell 初学者完全避免使用类型同义词,更有经验的 Haskell 程序员在某些特殊情况下很少使用它们。特别是,类型同义词是与组合非常有用的TypeFamilies扩展,并与组合有点用处ConstraintKindsRankNTypes扩展,但在其他方面往往超过有益的混乱,在我的经验。