#haskell #types
#haskell
Вопрос:
Я только изучаю Haskell и пытался написать простую программу для исключения первых n символов из a String
. Это то, что я получил:
cutString :: (Num n, String str) => n -> str -> str
cutString n str = case n of
0 -> tail str
n -> cutString (n-1) (tail str)
GHC выдает мне эту ошибку, и я не могу понять, почему:
`String' is applied to too many type arguments
In the type signature for `cutString':
cutString :: (Num n, String str) => n -> str -> str
Комментарии:
1. К вашему сведению:
cutString = GHC.List.drop
2. Спасибо! Я просто хотел написать свою собственную реализацию в любом случае, чтобы попрактиковаться, я только начал изучать Haskell сегодня
3. Примечание для современной аудитории: в настоящее время
cutString
также потребуетсяEq
в контексте, поскольку он использует буквальное соответствие шаблону.4. @Ben Millwood, спасибо, что указали на это. Мне было интересно, почему этот пример больше не работает в 2021 году, даже после корректировки приведенных ниже ответов. Какой сервер (Num n, Eq n) решает проблему.
Ответ №1:
String
это тип, а не класс типов, поэтому вы можете (должны) просто использовать его как есть в подписи типа.
cutString :: Num n => n -> String -> String
Комментарии:
1. Эта функция, конечно, имеет еще более простой тип
cutString :: Num n => n -> [a] -> [a]
. Кроме того,Num
в этом контексте не имеет особого смысла, поэтому, возможно, типIntegral i => i -> [a] -> [a]
или дажеInt -> [a] -> [a]
было бы лучше.2. @dflemstr Я уверен, что вы имеете в виду,
Integer -> [a] -> [a]
посколькуInt
это просто довольно грубая и беспринципная оптимизацияInteger
😉3. Ну, у вас редко бывает более 536870912 элементов в списке… Если мы хотим поговорить о семантике, я бы предпочел выбрать
Word
/Word64
в этом случае, а затем, возможно,Natural
(неотрицательныйInteger
), когда базовая библиотека в конечном итоге будет содержать его.4. Это утверждение устраняет мою путаницу в отношении использования type и type class.
Ответ №2:
Для справки, более старые GHC (т. Е. 7.2.2 или более ранние) раньше выдавали эту, скорее, более полезную ошибку:
Type constructor `String' used as a class
In the type `(Num n, String str) => n -> str -> str'
Действительно, это именно ваша проблема: String
это тип, и вы используете его как класс типа. Класс типа представляет собой набор типов, а не один тип, например, Integer
и Double
и Rational
— это все типы, принадлежащие классу типа Num
. Классы типов отображаются слева от =>
в types, где реальные типы и переменные типа отображаются справа от =>
.