Пользовательская функция фильтра с предикатом с использованием списка понимания - PullRequest
3 голосов
/ 20 мая 2019

Мне нужно разработать собственную функцию фильтра, аналогичную тому, как filter работает в Haskell, но с использованием понимания списка и предиката. Поэтому я бы положил lcFilter (>3) [1,2,3,4,5,6,10,444,3] в ghci, и он напечатал бы все числа больше 3.

Мой код основан на примере рекурсии, в котором я хорошо разбираюсь, но, похоже, я не могу преобразовать его в понимание списка. Он выглядит независимо от того, что я вставил в [x | x<-xs, p], всегда выдает ошибку компилятора. Я знаю, что p часть неверна. Я пробовал ==p, xs==p и почти все остальное, что мог придумать. Это заставляет меня думать, что какая-то другая часть может быть неправильной, но я действительно не уверен.

Вот код моей функции lcFilter. Я не уверен, что некоторые или все это неправильно, поэтому я публикую все это.

lcFilter :: (a -> Bool) -> [a] -> [a]
lcFilter _ [] = []
lcFilter p (x:xs) = [x | x<-xs, p]

Если я наберу lcFilter (>3) [1,2,3,4,5], он должен напечатать [4,5] точно так же, как стандартная функция Haskell filter.

1 Ответ

5 голосов
/ 20 мая 2019

Это так же просто, как

      [x | x <- xs, p x]

Поскольку p :: a -> Bool и xs :: [a], чтобы получить логическое значение, нам нужно применить функцию к аргументу;и согласно семантике понимания списка x :: a.

Правило вывода типа application :

          x :: a
          p :: a -> b
         -------------
          p x ::    b

И вам не нужно сопоставление с образцом, об этом позаботится понимание списка.

В общем, это

lcFilter :: (a -> Bool) -> [a] -> [a]
lcFilter p xs = [x | x <- xs, p]

Понимание списка - это весело.Они придерживаются одного правила:

    [ ... | x <- (xs            ++                ys), .... ]  ===
    [ ... | x <-  xs, ....  ]   ++   [ ... | x <- ys , .... ]

Как следствие, у нас также есть

    [ ... | x <- ([y]           ++                ys), .... ]  ===
    [ ... | x <-  [y], .... ]   ++   [ ... | x <- ys , .... ]  ===
    [ ...{x/y} | ....{x/y}  ]   ++   [ ... | x <- ys , .... ]  

, где {x/y} означает "заменить x на y во всем" .Таким образом, список [a,b,...,n] преобразуется по вашему определению в

    [  a,           b,          ...,    n        ]             ===>
    [  a | p a] ++ [b | p b] ++ ... ++ [n | p n  ]

Это может быть далее понято в терминах / служить хорошей иллюстрацией / концепций монад , илииз моноидов , но мы оставим это на другой день.:)

...