Откуда взяты эти значения в этой функции haskell? - PullRequest
3 голосов
/ 18 декабря 2008

Допустим, у меня есть следующая функция:

sumAll :: [(Int,Int)] -> Int
sumAll xs = foldr (+) 0 (map f xs)
  where f (x,y) = x+y

Результат sumAll [(1,1),(2,2),(3,3)] будет 12.

Что я не понимаю, так это откуда взялись значения (x,y). Ну, я знаю, что они происходят из переменной xs, но я не понимаю, как. Я имею в виду, что, выполнив приведенный выше код напрямую без ключевого слова where, это будет примерно так:

sumAll xs = foldr (+) 0 (map (\(x,y) -> x+y) xs)

И я не могу понять, в верхнем коде, как переменная f и переменные (x,y) представляют собой (\(x,y) -> x+y) лямбда-выражение.

Ответы [ 3 ]

6 голосов
/ 18 декабря 2008

Надеюсь, это поможет. Ключ в том, что f применяется к элементам списка, которые являются парами.

sumAll [(1,1),(2,2),(3,3)] 
      -- definition of sumAll
    = foldr (+) 0 (map f [(1,1),(2,2),(3,3)])
      -- application of map
    = foldr (+) 0 (f (1,1) : map f [(2,2),(3,3)])
      -- application of foldr
    = 0 + foldr (+) (f (1,1)) (map f [(2,2),(3,3)])
      -- application of map
    = 0 + foldr (+) (f (1,1)) (f (2,2) : map f [(3,3)])
      -- application of foldr
    = 0 + (f (1,1) + foldr (+) (f (2,2)) (map f [(3,3)]))
      -- application of f
    = 0 + (2 + foldr (+) (f (2,2)) (map f [(3,3)]))
      -- application of map
    = 0 + (2 + foldr (+) (f (2,2)) (f (3,3) : map f []))
      -- application of foldr
    = 0 + (2 + (f (2,2) + foldr (+) (f (3,3)) (map f [])))
      -- application of f
    = 0 + (2 + (4 + foldr (+) (f (3,3)) (map f [])))
      -- application of map
    = 0 + (2 + (4 + foldr (+) (f (3,3)) []))
      -- application of foldr
    = 0 + (2 + (4 + f (3,3)))
      -- application of f
    = 0 + (2 + (4 + 6))
    = 0 + (2 + 10)
    = 0 + 12
    = 12
5 голосов
/ 18 декабря 2008

В Haskell функции являются типами данных первого класса.

Это означает, что вы можете передавать функции, как и другие типы данных, такие как целые числа и строки.

В приведенном выше коде вы объявляете 'f' как функцию, которая принимает один аргумент (кортеж из двух значений (x, y)) и возвращает результат (x + y).

foldr - это другая функция, которая принимает 3 аргумента, двоичную функцию (в данном случае +) начальное значение (0) и массив значений для итератора.

Короче говоря, где f (x, y) = x + y '- это просто сокращенная область для

sumAll :: [(Int,Int)] -> Int
sumAll xs = foldr (+) 0 (map myFunctionF xs)

myFunctionF :: (Int,Int) -> Int
myFunctionF (x,y) = x + y

Редактировать : Если вы не знаете, как работает foldr, посмотрите Справочник по Haskell Zvon Ниже приведен пример реализации foldl / map.

foldl :: (a -> b -> b) -> b -> [a] -> b
foldl _ x [] = x
foldl fx (y:ys) = foldl f (f y x) ys

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = (f x) : (map f xs)
3 голосов
/ 20 декабря 2008

Не ответ, но я подумал, что должен указать, что ваша функция f:

f (x, y) = x + y

можно выразить как

f = uncurry (+)
...