import Data Map import List type Prefs Map Char Map Char Double type S

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import Data.Map
import List
type Prefs = Map [Char] (Map [Char] Double)
type SimilarityF = Prefs -> [Char] -> [Char] -> Double
type Person = [Char]
critics = fromList [
("Lisa Rose", fromList [("Lady in the Water", 2.5),
("Snakes on a Plane", 3.5),
("Just My Luck", 3.0),
("Superman Returns", 3.5),
("You, Me and Dupree", 2.5),
("The Night Listener", 3.0)]),
("Gene Seymour", fromList [("Lady in the Water", 3.0),
("Snakes on a Plane", 3.5),
("Just My Luck", 1.5),
("Superman Returns", 5.0),
("The Night Listener", 3.0),
("You, Me and Dupree", 3.5)]),
("Michael Phillips", fromList [("Lady in the Water", 2.5),
("Snakes on a Plane", 3.0),
("Superman Returns", 3.5),
("The Night Listener", 4.0)]),
("Claudia Puig", fromList [("Snakes on a Plane", 3.5),
("Just My Luck", 3.0),
("The Night Listener", 4.5),
("Superman Returns", 4.0),
("You, Me and Dupree", 2.5)]),
("Mick LaSalle", fromList [("Lady in The Water", 3.0),
("Snakes on a Plane", 4.0),
("Just My Luck", 2.0),
("Superman Returns", 3.0),
("The Night Listener", 3.0),
("You, Me and Dupree", 2.0)]),
("Jack Matthews", fromList [("Lady in the Water", 3.0),
("Snakes on a Plane", 4.0),
("The Night Listener", 3.0),
("Superman Returns", 5.0),
("You, Me and Dupree", 3.5)]),
("Toby", fromList [("Snakes on a Plane", 4.5),
("You, Me and Dupree", 1.0),
("Superman Returns", 4.0)]),
("xa4a", fromList [])
]
sim_distance :: SimilarityF
sim_distance prefs person1 person2 =
let squares = intersectionWith (\x y->(x-y)**2) (prefs!person1) (prefs!person2)
in
if length (elems squares) == 0 then 0
else 1/(1+(sum (elems squares)))
sim_pearson :: SimilarityF
sim_pearson prefs p1 p2 =
let
si = intersectionWith (\x y->1) (prefs!p1) (prefs!p2)
n = fromIntegral (length (elems si))
sum1 = sum [prefs!p1!it | it <- keys si]
sum2 = sum [prefs!p2!it | it <- keys si]
sum1Sq = sum [prefs!p1!it**2 | it <- keys si]
sum2Sq = sum [prefs!p2!it**2 | it <- keys si]
pSum = sum [prefs!p1!it * prefs!p2!it | it <- keys si]
num = pSum - (sum1*sum2/n)
den = sqrt ((sum1Sq - sum1**2/n)*(sum2Sq-sum2**2/n))
in
if or [n==0, den==0] then 0
else num/den
topMatches :: Prefs -> Person -> Int -> SimilarityF -> [(Double,[Char])]
topMatches prefs person n similarity =
let scores = [(similarity prefs person other, other) | other <- keys prefs, other/=person]
in take n (reverse (sort scores))