haskell и определение типа функций. пара вопросов - PullRequest
3 голосов
/ 23 февраля 2010

если я сделаю any isUpper "asBsd", я получу True.
здесь вторым элементом any является строка.
но если я сделаю это:

any ("1" `isInfixOf`) ["qas","123","=-0"]

второй элемент any - это список строк.
как и почему эта разница между этими двумя функциями?

другой пример.
если я напишу filter isUpper "asdVdf", я получу "V".
здесь вторым фильтруемым элементом является строка.
но если я напишу это:
filter (isUpper . head) ["abc","Vdh","12"], я получу ["Vdh"].
как видите, вторым фильтрующим элементом теперь является список строк.
почему есть различия и как haskell знает, что это правильно в обоих случаях?

чтобы подвести итог:
я не понимаю, как в той же функции один раз haskell получает второй элемент, который является строкой, а в другой раз haskell получает список строк во втором элементе.
один раз это произошло в функции any, а другое - в функции filter.
откуда haskell (и я) узнаем, что это правильно в обоих случаях?

спасибо: -).

Ответы [ 3 ]

11 голосов
/ 23 февраля 2010

Поскольку isUpper является функцией Char -> Bool, а "1" ‘isInfixOf‘ и isUpper . head являются [Char] -> Bool функциями


"1" `isInfixOf` xxx

можно переписать как

isInfixOf "1" xxx

Мы знали, что тип isInfixOf равен [a] -> [a] -> Bool 1 . Теперь первый аргумент isInfixOf - это "1", который имеет тип [Char], так что мы можем вывести a это Char:

     isInfixOf :: [a]    -> [a] -> Bool
       "1"     :: [Char]
//∴ a = Char and
 isInfixOf "1" ::           [a] -> Bool
                =        [Char] -> Bool

Это означает, что isInfixOf "1" теперь является функцией [Char] -> Bool.

Теперь тип any является функцией (a -> Bool) -> [a] -> Bool. Как указано выше,

               any :: (a      -> Bool) -> [a] -> Bool
     isInfixOf "1" :: ([Char] -> Bool)
 //∴ a = [Char] and

любой (isInfixOf "1") :: [a] -> Bool = [[Char]] -> Bool

Чтобы удовлетворить ограничения типа any (isInfixOf "1"), аргумент должен быть списком строк.


Теперь рассмотрим isUpper. Тип isUpper является Char -> Bool. Следовательно:

              any :: (a    -> Bool) -> [a] -> Bool
          isUpper :: (Char -> Bool)
//∴ a = Char and
      any isUpper ::                   [a] -> Bool
                   =                [Char] -> Bool

Так что any isUpper нужно взять только строку вместо списка строк.


Наконец, isUpper . head. В Haskell типы соответствующих функций:

 filter :: (a -> Bool) -> [a] -> [a]
   head :: [a] -> a
isUpper :: Char -> Bool
    (.) :: (b -> c) -> (a -> b) -> a -> c

Следовательно, для filter isUpper, a = Char и типа [Char] -> [Char], т. Е. Ему нужно принять строку в качестве параметра.

И 2

            (.) :: (b    -> c   ) -> (a   -> b) -> a -> c
        isUpper :: (Char -> Bool)
           head ::                   ([b] -> b)
//∴ c = Bool, b = Char, a = [b] = [Char], and
 isUpper . head ::                                 a -> c
                =                             [Char] -> Bool

Таким образом, для filter (isUpper . head) у нас есть a = [Char], а типом является [[Char]] -> [[Char]], то есть он должен принимать список строк в качестве параметра.


Примечание:

  1. Тип isInfixOf на самом деле (Eq a) => [a] -> [a] -> Bool, поскольку равенство должно быть допустимым для типа a, но это не имеет значения в нашем анализе.
  2. Я временно изменил переменную a на b для head, но это не имеет значения.
5 голосов
/ 23 февраля 2010

Строка на самом деле просто список символов, а [Char]. Так что, если хотите, «hello» - сокращение от ['h', 'e', 'l', 'l', 'o']. Поэтому в обоих случаях вы получаете список чего-то, просто один случай - это список Char, а другой - список строк (или список списков символов, если хотите).

4 голосов
/ 23 февраля 2010

Ну, это полиморфизм. Тип any равен (a -> Bool) -> [a] -> Bool, где переменная типа a может быть любой, какой вам нравится. В первом случае это Char - поскольку второй аргумент является списком Char s - и тип становится (Char -> Bool) -> String -> Bool (помните, что [Char] совпадает с String!); во втором a равен String, а тип становится (String -> Bool) -> [String] -> Bool.

Смысл filter аналогичен.

...