Haskell-переопределение (скрытие) арифметических операторов
Я хочу переопределить несколько арифметических операторов в Haskell, чтобы сделать их более расширяемыми и общими.
Э. Г.
class Mul a b c | a b -> c where
(*) :: a -> b -> c
это, кажется, работает в сочетании с
import Prelude hiding ((*))
скрытие стандарта *
оператора. Но, конечно, все обычные умножения также должны работать, поэтому мне нужно определить что-то вроде
instance (Num t) => Mul t t t where
(*) = ??
как я могу получить доступ к исходной *
оператор (Prelude.(*)
не работает) здесь и как я могу необходимо определить тип экземпляра так, чтобы 1 * 1
не конфликтует с Ограничение Monomorpism?
редактировать -
import qualified
хороший совет, спасибо.
но, к сожалению, это заставило меня принести все стандартные методы в области явно. Я просто хочу иметь возможность переопределить некоторые привязки, оставив остальные без изменений.
Итак, есть ли комбинация обоих? Что-то вроде
import Prelude qualified ((*))
4 ответов
ответ на отредактированный вопрос:
можно сделать
import Prelude hiding ((*))
import qualified Prelude as P
чтобы получить доступ ко всем функциям прелюдии, кроме (*)
обычным способом и до (*)
через P
префикс:
x = 5 + 3 -- works
y = 5 P.* 3 -- works
z = 5 * 3 -- complains about * not being in scope
экземпляр
instance (Num t) => Mul t t t where
(*) = ??
в значительной степени победит цель определения Mul t t t
в первую очередь, без злоупотребления расширениями, чтобы позволить {-# LANGUAGE OverlappingInstances #-}
.
к сожалению, "правильный", если болезненный ответ должен пройти экземпляр за экземпляром и сделать
import Prelude hiding ((*))
import qualified Prelude
instance Mul Int Int Int where
(*) = (Prelude.*)
instance Mul Double Double Double where
(*) = (Prelude.*)
instance Mul Int Double Double where
...
instance Mul (Complex Float) (Complex Double) (Complex Double)
...
в противном случае то, как главы экземпляров будут разрешены в компиляторе( без обратного отслеживания), вероятно, заставит ваши новые экземпляры вызвать компиляцию взорваться, когда вы перейдете к фактическому использованию их.
тем не менее, вы можете, по крайней мере, облегчить боль для случаев, о которых вы не думали:
newtype Other a = Other a
instance Num a => Mul (Other a) (Other a) (Other a) where
Other a * Other b = Other (a Prelude.* b)
это, по крайней мере, позволит им просто использовать вашу оболочку newtype, если они не хотят идти и определять Mul и все ваши другие классы сами.
было несколько попыток сделать такие вещи.
во-первых,
Как я могу получить доступ к исходному оператору * (прелюдия.(*) не работает)
вам потребуется:
import qualified Prelude
теперь вы можете использовать, например, (Prelude.*). Это менее агрессивно, чем" язык NoImplicitPrelude", который также приведет к локальному использованию >>= и так далее, чтобы отскочить от ваших определений.
вот примеры альтернативы других людей прелюдии:
- http://hackage.haskell.org/package/prelude-plus -- более простая прелюдия (?)
- http://hackage.haskell.org/package/numeric-prelude -- альтернативная числовая иерархия.
Я могу ответить на первый вопрос. Скрытие оператора ( * ) действительно скрывает его, поэтому вы не можете добраться до него. Тем не менее, вы можете импортировать прелюдию квалифицированный:
import qualified Prelude as P
foo = 3 P.* 14 -- == 42
Я думаю, что это делает то, что вы хотите.