我有这个代码,我试图创建以计算记录数量并打印它们,我似乎无法使它工作我不断得到函数reportReg的错误应用于一个参数但其类型[String]没有。
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
此外,有更简单的方法吗?
答案 0 :(得分:5)
问题:
您已经为reportReg
提供了一种字符串列表:
reportReg :: [String]
这只是一个值,或0参数的函数。这解释了你得到的错误 - 试图给它一个参数,但它没有。
<强>解决方案:强>
您希望在reportReg
中执行IO操作,因此您应该更改类型注释:
reportReg :: [String] -> IO ()
- 或 -
<强>问题:强>
report
的返回类型错误。它必须与reportReg
的相同。但是reportReg :: String -> IO ()
,而report :: [[String]] -> String -> [String]
!
几种可能的解决方案:
reportReg
删除IO操作,使其类型为[String] -> [String]
。我强烈建议这样做 - 任何语言的IO总是很痛苦,但Haskell的酷炫之处在于它会让你感受到痛苦 - 从而激励你尽可能地避免IO!report
的类型更改为[[String]] -> String -> IO ()
懒人的解决方案:
我将您的代码复制到文本文件中,删除了注释(不做其他更改),并将其加载到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
它有效--Haskell推断出类型! 但它可能不会做你想要的。
答案 1 :(得分:4)
我想我知道发生了什么。
reportReg :: [String]
声明reportReg
是字符串列表。但是您希望reportReg
成为函数(在->
类型中标记),其中采用字符串列表:
reportReg :: [String] -> ???
现在唯一的问题是取代???
的内容 - reportReg
会返回什么内容?
这就是Haskell与其他语言不同的地方。它返回 I / O操作。它是一个将字符串列表映射到动作的函数 - 即,做而不是要返回的值(因此它确实返回值 - 但该值的目的是描述要执行的操作) 。我们写了这种描述操作的值IO ()
的类型。所以:
reportReg :: [String] -> IO ()
答案 2 :(得分:0)
其他人已经指出了导致错误的原因,但我会就你提出的另一个问题发表评论:
此外,有更简单的方法吗?
是的,计算列表元素的简单方法是使用length
函数。如果需要计算满足谓词的元素数量,则可以计算过滤结果的长度。我不完全理解你的代码(例如,typ
参数的作用是什么?),但这是一个例子(可能不完全相同):
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)
我建议主要建议从do块中提取尽可能多的代码(上面的代码仍然可以在这方面使用改进)。尝试使用纯代码完全解决您的问题,并仅使用IO monad打印结果。