2016-03-02 4 views
1
divide_list :: Int -> [Int] -> [Int] -> [Int] -> ([Int], [Int]) 

divide_list n [] l r = (l,r) 
divide_list n (h:t) l r = 
    if h <= n 
     then divide_list n t (h:l) r 
     else divide_list n t l (h:r) 

Как вы можете видеть, моя функция принимает список Int. Как изменить этот код, чтобы получить более общий тип? Я имею в виду, например, список String и т. Д.Обобщение типов аргументов

+2

Одно простое решение состоит в оценке функции без сигнатуры типа, и пусть ghci вывести тип для вас. Он должен обобщать 'Int' на' Ord a => a'. – zakyggaps

+0

Что значит: «Ord a => a»? – Gilgamesz

+1

Это любой тип 'a' с экземпляром' Ord'. Это необходимо для использования '<=' в вашей функции. – zakyggaps

ответ

3

Для того чтобы сделать функцию полиморфной, вам нужно указать переменную типа в подписи функции. Переменные типа должны быть указаны в нижнем регистре, чтобы отличать их от конкретных типов, которые указаны в верхнем регистре.

divide_list :: a -> [a] -> [a] -> [a] -> ([a], [a]) 

Цитата Нежное Введение в Haskell учебник:

Haskell также включает в себя полиморфные типы --- типы, которые повсеместно количественно определенным образом по всем типам. Полиморфный тип выражений существенно описывает семейства типов. Например, (forall a) [a] - это семейство типов, состоящих из каждого типа a, типа списков a. Списки целых чисел (например, [1,2,3]), списки из символов (['a', 'b', 'c']), даже списки списков целых чисел и т. Д. - это все члены этого семьи.

EDIT после вопроса в комментарии:

Обратите внимание, что в определении функции вы используете <=. Это функция, определенная в классе Ord, поэтому вам необходимо ограничить полиморфный тип экземпляром этого класса.

divide_list :: (Ord a) => a -> [a] -> [a] -> [a] -> ([a], [a]) 
+0

ОК, после этого у меня возникла ошибка компиляции (это очевидно, потому что Хаскелл не знает, что это значит: ((<=) ru). Но как его восстановить? – Gilgamesz

+1

Эта подпись типа слишком полиморфна - вам нужно экземпляр 'Ord a' для бит' e <= n'. – Cactus

+0

Хорошо. Как определить свой собственный тип и наложить его на Ord? – Gilgamesz

1

Единственный аспект Int с вы используете, что данный h и n, вы можете вычислить h <= n. Это обобщается в Ord классе типов, так что ваша функция может быть полиморфной по любому выбору типа переменной a, пока есть Ord a экземпляр:

divide_list :: (Ord a) => a -> [a] -> [a] -> [a] -> ([a], [a]) 
+0

Что это значит '=>'? – Gilgamesz

+0

https://www.haskell.org/tutorial/classes.html – Cactus

Смежные вопросы