#haskell #overriding
#haskell #переопределение
Вопрос:
Я пытаюсь определить функцию, которую я хочу вести немного по-другому в зависимости от того, какой тип данных передается в качестве аргумента, строк и целых чисел. Как бы это сделать? Или есть какие-либо изменения, которые вы могли бы предложить, чтобы каким-то образом объединить эти две функции в одну функцию. Я читал, что попытка проверки типа данных не очень похожа на haskell, поэтому я подумал, что переопределение может быть способом сделать это, но компилятору не нравится дубликат:(
jumpTo :: Int -> [String] -> [String]
jumpTo index t = do
let (x,y) = splitAt index t
init x [last x "QQ"] y
jumpTo :: String -> [String] -> [String]
jumpTo string t = do
pos <- [fromJust (findWord string t)]
let (x,y) = splitAt pos a
init x [last x "QQ"] y
Проще говоря, мне нужна функция, jumpTo
которой можно передать String
или Int
в качестве первого аргумента; если это строка, я нахожу ее в списке, а для целого числа я сразу выполняю операции с индексом. Просто кажется более элегантным иметь одну и ту же функцию, выполняющую это.
Комментарии:
1. В этом и заключается идея классов типов : learnyouahaskell.com/types-and-typeclasses он используется для «специального полиморфизма».
2. насколько я понимаю эту статью, классы типов позволяют вам работать с разными типами данных в одной и той же функции, но фактически не переопределяют само определение функции?
3. ну, вы определяете свой
jumpTo
в классе типовclass JumpTo a
какjumpTo :: a -> [String] -> [String]
, а затем объявляете два экземпляра:instance JumpTo Int
, иinstance JumpTo String
. Для каждогоinstance
вы можете предоставить другую реализацию. На самом деле такshow
работает, например: каждый тип определяет свой конкретный способshow
.
Ответ №1:
Именно в этом заключается идея классов типов: вы определяете свою функцию (или группу функций) не саму по себе, а как принадлежащую классу типов, который помечен переменной типа (или несколькими). Затем вы определяете один или несколько экземпляров класса type с различными типами, заменяющими эту переменную типа, и вы определяете отдельные тела для функции в каждом экземпляре. Конечным результатом является то, что функция имеет различное тело в зависимости от типов ее аргументов или результата.
В вашем примере:
class JumpTo a where
jumpTo :: a -> [String] -> [String]
instance JumpTo Int where
jumpTo index t = do
let (x,y) = splitAt index t
init x [last x "QQ"] y
instance JumpTo String where
jumpTo string t = do
pos <- [fromJust (findWord string t)]
let (x,y) = splitAt pos a
init x [last x "QQ"] y
Комментарии:
1. спасибо, теперь это имеет смысл! При компиляции я получаю недопустимое объявление экземпляра для экземпляра String, переписывание его в [] Char также не помогает. Я попробовал «обещающий» haskell, что я не буду определять какие-либо перекрывающиеся экземпляры, однако, используя функции, я получаю ошибки, выдаваемые мне, говоря, что это слишком неоднозначно. :[ как же тогда использовать String?
2. @peterxz Вам нужно будет включить
TypeSynonymInstances
иFlexibleInstances
. Ваш написанный код по-прежнему не будет компилироваться после того, как вы это сделаете, но это не связанная с этим проблема.