Haskell 中类型不匹配的问题以及在哪里可以找到好的指南

Problems with mismatched Types in Haskell and where to find good guides

首先我想问一下我可以在哪里提高我的 haskell 技能,每当我遇到困难时,我找不到相关的教程或任何可以帮助我的东西,我正在尝试和错误地找出语法事情及其令人沮丧,我可以在这里寻求每个问题的帮助,但我觉得很麻烦,应该首先有其他路线,就像我在 C# 或 Python 中编程时,我通常可以四处搜索类似的问题并解决我自己,但 Haskell 就不那么重要了,所以任何教程、智慧、课程或任何东西都将不胜感激! (我正在创建一个数据类型并希望通过各种函数来操作这些类型的列表)

我一直遇到的错误是类型与预期类型不匹配。

data Song = Song {title :: String,
                  artist :: String,
                  sales :: Int} deriving(Eq, Show)

database :: [Song]
database = [s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22]


s1 = Song "Amon Amarth" "Ravens flight"  1  --this seems... inefficient  lots of repetition here...
s2 = Song  "Amon Amarth" "Shield wall"  11
s3 = Song  "Amon Amarth" "The way of vikings"  105
s4 = Song  "Elijah Nang" "Journey to the west"  1000
s5 = Song  "Elijah Nang" "Tea house"  7
s6 = Song  "Pink Floyd" "Wish you were here"  123
s7 = Song  "Amon Amarth" "Raise your horns"  9001
s8 = Song  "NLE Choppa" "Walk 'em down'"  69420
s9 = Song  "Elijah Nang" "Kumite"  1337
s10 = Song  "NLE Choppa" "Shotta flow 6"  511
s11 = Song  "Pink Floyd" "Comfortably numb"  9
s12 = Song  "Pink Floyd" "Shotta flow 6"  711  -- changed to match the name of an nle choppa song as requested
s13 = Song  "Johannes Chrysostomus Wolfgangus Theophilus Mozart" "Requiem"  10203948
s14 = Song  "Elijah Nang" "Kenjutsu water style"  1
s15 = Song  "NLE Choppa" "Shotta flow 5"  1
s16 = Song "Pink Floyd" "High hopes"  1
s17 = Song "Amon Amarth" "Deceiver of the gods"  1
s18 = Song  "Johannes Chrysostomus Wolfgangus Theophilus Mozart" "Turkish march"  1
s19 = Song  "Chance The Rapper" "Cocoa butter kisses"  1
s20 = Song  "Chance The Rapper" "Favourite song"  1
s21 = Song "Chance The Rapper" "Hot shower"  1
s22 = Song "Chance The Rapper" "High hopes"  1


-- give this function an index of 0 every time to start with, give it a artist and a track, then it will output the sales for that track of the artist

getTrackSale :: Int -> String -> String -> Int --(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") --uses index 0, and that artist + track, should return the stored sales for that combo.


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

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

getSale :: Song -> Int
getSale (Song _ _ x) = x

这给我的错误是

123.hs:42:88: error:
    * Couldn't match expected type `Int'
                  with actual type `String -> String -> Int'
    * Probable cause: `getTrackSale' is applied to too few arguments
      In the expression: getTrackSale (database !! index)
      In an equation for `getTrackSale':
          getTrackSale index artist track
            | ((getArtist (database !! index) == artist)
                 && (getTrack (database !! index) == track))
            = getTrackSale (database !! index)
            | otherwise = getTrackSale (index + 1 artist track)
   |
42 |   | ((getArtist(database!!index) == artist) && (getTrack(database!!index) == track)) = getTrackSale(database!!index)

听起来好像混淆了我想给出的输入变量和我想要的输出变量,我不知道我做错了什么。

Stack Overflow question 及其 top-voted 答案可能会有所帮助。这是一个古老的答案,但那里提供的大部分资源仍然有用。特别是,我发现您在 Haskell 语法的一些基本方面仍然遇到问题,并且通过该问题的多个教程肯定会帮助您解决这个问题。

Haskell 的类型系统极其严苛,因为程序 必须 类型正确才能编译。同时,类型系统也极其强大和复杂。最终结果是,简单的语法错误可能会被编译器完全误解为试图使用强大的 type-level 功能,并且由此产生的类型错误可能会完全令人费解。新手运行一直都遇到这个问题,但即使是经验丰富的Haskell程序员运行也会陷入他们真的不理解的类型错误,每个人都必须做一点trial-and-error有时想办法解决问题。

无论如何,您的具体问题是:

  1. 当您打算使用 getSale 时,您不小心使用了 getTrackSale,因此您将一个参数传递给需要三个参数的函数。这就是错误消息的内容。
  2. 调用带有多个参数的 haskell 函数时,正确的语法是 f x y z,而不是 f (x y z)。表达式 f (x y z) 被编译器完全误解为试图将“函数”x 应用于参数 yz,然后将结果作为单个传递f!
  3. 的参数

如果您将 getTrackSale 修改为:

getTrackSale :: Int -> String -> String -> Int --(index, artist, track, sales)
getTrackSale index artist track
  | ((getArtist(database!!index) == artist) && (getTrack(database!!index) == track))
  = getSale (database!!index)  -- use getSale, not getTrackSale
  | otherwise = getTrackSale (index+1) artist track   -- pass three parameters

和您的 task2 定义为:

task2 = getTrackSale 0 "Chance The Rapper" "Hot Shower" -- use three parameters

你的程序type-checks。当你 运行 它时,它崩溃了,但这只是因为 "Hot Shower" 不匹配 "Hot shower"。如果你修复了大小写,你的程序就可以正常工作。

总而言之,看起来你做得很好。祝你继续 Haskell 黑客攻击好运,请随时提出更多问题。除非您有 50 sock-puppet 个我们不知道的帐户,否则您到目前为止提出的两个问题很难被视为让自己成为“讨厌鬼”。