Haskell:连接列表简单问题

时间:2016-03-13 21:48:58

标签: haskell

我有一个硬编码列表,我想连接到列表列表。

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)])]

3 个答案:

答案 0 :(得分:4)

你有两个问题。

  1. 鉴于addFilm的定义,类型签名应该只是addFilm :: [Film],因为您没有使用已定义的参数,也没有在调用它时实际传递任何参数。

  2. 由于您在IO monad中使用该功能,因此无法像这样直接调用它。最简单的解决方法是简单地使用其返回值作为print的参数:

    main = print addFilm
    
  3. 另一个解决方案是保留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类型)。