添加到列表和递增 - Haskell

时间:2014-07-18 09:55:28

标签: haskell

import Data.Char

-- Sample test data
testData :: [Movies]
testData = [("Me and My Broken Heart","Rixton"),
            ("It’s My Birthday","will.i.am"),
            ("Problem","Ariana Grande")]

-- record a sale of a track 
record :: [Movies] -> String -> String 
record t a = []
record ((t, a): xs) a a
    | t == a && a == a = [(t,a)]
    | otherwise = record xs a t

正确的输出应该是数据库的修改版本。

2 个答案:

答案 0 :(得分:6)

首先,因为你似乎正在学习,所以关于风格的一些注释:在这种情况下,以单数形式命名一个销售是一种惯例,并且列表他们用复数形式,即:

type Sale = (String, String, Int)
type Sales = [Sale]

更好的是,通常会(根据预期的用途和品味)将Sale转换为新类型或完整的ADT,因为这样可以提供更多抽象和类型安全。

其次,对于您的实际问题:您所看到的行为来自模式匹配的顺序。在你的第一场比赛中,

recordSale testData aTitle anArtist = []
在第二个模式可以应用之前,

testDate匹配任何列表,也是非空的列表。将其更改为

recordSale [] _ _ = []

你不会再获得空名单了。另外,正如@Aleksandar指出的那样,在列表不为空但过滤条件不匹配的情况下,您不应忘记保留列表的init。

答案 1 :(得分:4)

Haskell是一种函数式语言,它在类型系统中很好地封装了对数据的有状态修改。通常的方式"变异" Haskell中的值将是使用有状态计算(在STState Monad中)或仅使用递归并复制值。我想你应该先学习后者。

如果[]aTitle与列表中的任何条目都不匹配,您使用的功能将返回anArtist。否则返回一个包含一个单个元素的列表,即新修改过的列表。

您需要在遍历时逐步建立列表。记住,你基本上是在复制它:

-- record a sale of a track recordSale :: [Sales] -> String -> String -> [Sales] recordSale [] aTitle anArtist = [] recordSale ((title, artist, qty): xs) aTitle anArtist | title == aTitle && artist == anArtist = (title, artist, qty+1):recordSale xs aTitle anArtist | otherwise = (title,artist,qty):recordSale xs aTitle anArtist

这应该会给你正确的结果。请注意这里有什么不同:你在两个案例中对函数进行了递归调用,在这两种情况下,你也要将修改或未修改的当前元素附加到列出你的建设。

您还应该考虑您的数据结构。具有注释的元组不是构建复杂数据结构的非常好的方法。尝试

data Record = Record { title :: String, artist :: String, quantity :: Integer }

你甚至可以像newtype那样制作几个newtype Title = Title String。请记住,在Haskell中创建数据类型很便宜,而且你应该不断地这样做。