我有一个硬编码列表,我想连接到列表列表。
import Data.List (nub, sort)
import System.IO
type Title = String
type Director = String
type Year = Int
type Mark = Int
type Rating = (String, Int)
-- Define Film type here
type Film = (Title, Director, Year, [Rating])
-- Define database type here
type Database = [Film]
main = do
addFilm
print testDatabase
testDatabase :: [Film]
testDatabase = [("Casino Royale", "Martin Campbell", 2006, [("Garry", 8)])]
addFilm :: [Film] -> Film -> [Film]
addFilm a b = ("The BFG", "Steven Speilberg", 2016, []) : testDatabase
我收到错误
Couldn't match expected type ‘IO a0’
with actual type ‘[Film] -> Film -> [Film]’
Probable cause: ‘addFilm’ is applied to too few arguments
In a stmt of a 'do' block: addFilm
In the expression:
do { addFilm;
print testDatabase }
我觉得我错过了一些相当简单的事情,但对于我的生活,我无法看到它。
我的预期输出是这样的
[("The BFG","Steven Speilberg",2016,[]),("Casino Royale","Martin Campbell",2006,[("Garry",8)])]
答案 0 :(得分:4)
你有两个问题。
鉴于addFilm
的定义,类型签名应该只是addFilm :: [Film]
,因为您没有使用已定义的参数,也没有在调用它时实际传递任何参数。
由于您在IO monad中使用该功能,因此无法像这样直接调用它。最简单的解决方法是简单地使用其返回值作为print
的参数:
main = print addFilm
另一个解决方案是保留addFilm
的类型签名,并实际使用您传递的参数,然后使用适当的参数调用它。
addFilm :: [Film] -> Film -> [Film]
addFilm a b = b : a
-- addFilm = (:)
main = do
let newDatabase = addFilm testDatabase ("The BFG", "Steven Speilberg", 2016, [])
print newDatabase
答案 1 :(得分:2)
addFilm
需要两个参数
addFilm :: [Film] -> Film -> [Film]
addFilm a b = ....
然而你在主要没有
的情况下调用它main = do
addFilm
编译器告诉你这里需要两件事
main = do
addFilm thing1 thing2
答案 2 :(得分:1)
您已将addFilm
定义为带有两个参数的函数(即使您不对这些参数执行任何操作),但在使用它时不提供任何参数。这就是错误消息告诉你的。
但即使您提供参数(或从定义中删除参数并将类型更改为[Film]
),您仍然无法在addFilm
中使用main
作为语句{1}}阻止。 addFilm a b
会生成[List]
类型的值,但main
的块中的语句必须包含IO a
类型(对于某些a
)。
看起来您可能会认为:
是一种影响testDatabase
价值的副作用操作。它不是,也没有任何东西能够影响testDatabase
的价值。您目前对addList
的定义与此相同:
addList a b = [("The BFG", "Steven Speilberg", 2016, []), ("Casino Royale", "Martin Campbell", 2006, [("Garry", 8)])]
这只是一个包含两部电影的列表。所以使用它作为一个声明是没有意义的 - 它没有副作用(如果确实如此,它必须有一个IO
类型)。