I have this code that I tried to create to count amount of records and print them, I cant seem to get it working I constantly get errors about a function reportReg being applied to one argument but its type [String] having none.
report :: [[String]] -> String -> [String]
report (x:xs) typ = do
case typ of
"registrations" -> reportReg (map head xs)
"completions" -> reportReg (map head xs)
reportReg :: [String]
reportReg [x] = do
print x
print 1
reportReg (x:xs) = do
let count = instances x (x:xs)
print x
print count
let newlist = filter (==x) (x:xs)
reportReg newlist
instances::String->[String]->Int
instances x [] = 0
instances x (y:ys)
| x==y = 1+(instances x ys)
| otherwise = instances x ys
Also, is there an easier way to do this?
Problem:
You've given reportReg
a type of list of string:
reportReg :: [String]
This is simply a value, or a function of 0 arguments. That explains the error you were getting -- trying to give it an argument, but it takes none.
Solutions:
It looks like you want to do IO actions in reportReg
, so you should change the type annotation:
reportReg :: [String] -> IO ()
-- or --
Problem:
report
's return type is wrong. It has to be the same as that of reportReg
. But reportReg :: String -> IO ()
, whereas report :: [[String]] -> String -> [String]
!
A couple possible solutions:
reportReg
, so that its type is [String] -> [String]
. I'd strongly suggest doing this -- IO in any language is always a pain, but the cool thing about Haskell is that it makes you feel the pain -- thereby giving you an incentive to avoid IO as much as possible! report
to [[String]] -> String -> IO ()
Lazy man's solution:
I copied your code into a text file, removed the annotations (making no other changes), and loaded it into ghci
:
Prelude> :load typef.hs
[1 of 1] Compiling Main ( typef.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t report
report :: (Eq a, Show a) => [[a]] -> [Char] -> IO ()
*Main> :t reportReg
reportReg :: (Eq a, Show a) => [a] -> IO ()
*Main> :t instances
instances :: (Num t, Eq a) => a -> [a] -> t
It works -- Haskell infers the types! But it may not do what you want.
I think I see what is going on.
reportReg :: [String]
declares that reportReg
is a list of strings. But you want reportReg
to be a function (marked in the type by ->
) which takes a list of strings:
reportReg :: [String] -> ???
Now the only question is what goes in place of the ???
-- what does reportReg
return?
This is where Haskell differs from every other language. It returns an I/O action . It is a function which maps lists of strings to actions -- namely, something to do rather than a value to return (so it does return value -- but that value's purpose is to describe what to do). We write the type of such action-describing values IO ()
. So:
reportReg :: [String] -> IO ()
Other folks have pointed out the cause for your error, but I will comment on the other issue you've raised:
Also, is there an easier way to do this?
Yeah, the simple way to count the elements of a list is to use the length
function. If you need to count how many elements satisfy a predicate, you can take the length of the result of filtering. I don't completely understand your code (eg, what's that typ
argument doing?), but here's an example (that probably doesn't do exactly the same):
reportReg :: [a] -> IO ()
reportReg [] = do return ()
reportReg xs = do print (head x)
print (count x xs)
reportReg (tail xs)
count :: a -> [a] -> Integer
count x xs = length (filter (==x) xs)
The main piece of advice I would suggest it to pull out as much code as possible from the do blocks (my code above still could use improvement in that regard). Try to solve your problem completely in terms of pure code, and use the IO monad only to print the result.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.