1

firstly i want to ask where can i look to improve my skills with haskell, whenever i get stuck i cant find relevant tutorials or anything to help me, im using trial and error to figure out syntax for things and its frustrating, i can ask for help with each problem here but i feel like a nuisance and that there should be other routes first like when i program in C# or Python i can usually search around for similar problems and solve it myself, but less so with Haskell, so any tutorials, wisdom, courses or whatever would be greatly appreciated! (im creating a data type and wish to manipulate a list of those types through a variety of functions)

the error i keep having is mismatched types with the expected types.

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

this give me the error of

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)

it sounds like it's confusing what input variables i want to give and what output variables i want, i don't know what i'm doing wrong.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • 1
    Recommended learning resources s is specifically off topic on Stack Overflow - however I am happy to recommend [LYAH](http://learnyouahaskell.com/) as the best beginners' resource I have come across. (And it's also how I got started with Haskell.) – Robin Zigmond Aug 05 '20 at 18:33
  • 1
    The error is in `getTrackSale`, which isn't posted. Please post a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Mark Seemann Aug 05 '20 at 18:44
  • 1
    getTrackSale is applied to too few arguments, as the error message suggests. I recommend learning a new programming language by reading a book from the beginning. It looks like you're struggling with basic syntax. Search the Haskell reddit for recent recommendations – jberryman Aug 05 '20 at 18:59
  • thank you, i have used "Learn you a Haskell for a great good" before and it is definitely the best resource i had managed to find, i will check the reddit too! – Kane Austin Aug 05 '20 at 21:18

1 Answers1

2

This Stack Overflow question and its top-voted answer may be helpful. It's an old answer, but most of the resources given there are still useful. In particular, I can see that you're still having trouble with some basic aspects of Haskell syntax, and working through multiple tutorials from that question will definitely help you with this.

Haskell's type system is extremely unforgiving, in that a program must be precisely type correct in order to compile. At the same time, the type system is also extremely powerful and complex. The end result is that simple syntax errors can be totally misinterpreted by the compiler as attempts to use powerful type-level features, and the resulting type errors can be completely baffling. Beginners run up against this all the time, but even experienced Haskell programmers run into type errors that they really don't understand, and everyone has to do a little trial-and-error to figure things out sometimes.

Anyway, your specific issues are:

  1. You accidentally used getTrackSale when you meant to use getSale, so you passed a single parameter to a function that expected three parameters. That's what the error message was about.
  2. When calling a haskell function with multiple arguments, the correct syntax is f x y z, not f (x y z). The expression f (x y z) is completely misinterpreted by the compiler as an attempt to apply the "function" x to the arguments y and z, and then pass the result as a single parameter to f!

If you fix getTrackSale to read:

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

and your task2 definition to read:

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

your program type-checks. When you run it, it crashes, but only because "Hot Shower" doesn't match "Hot shower". If you fix the capitalization, your program works fine.

All in all, it looks like you've done a pretty good job. Good luck with your continued Haskell hacking, and please feel free to ask more questions. Unless you have 50 sock-puppet accounts we don't know about, the two questions you've asked so far could hardly be considered making yourself a "nuisance".

K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71
  • 2
    thanks so much for the help, and thank you for being so kind about it! you have renewed my interest in finishing this program :-) – Kane Austin Aug 05 '20 at 21:14