#haskell #phantom-types
#haskell #фантомные типы
Вопрос:
У меня есть фантомный тип:
newtype MyType a = {getSth :: SthType}
Как я могу сравнить MyType a1
и MyType a2
по отношению к результату a1
и a2
сравнения, т.Е. Если a1 < a2
тогда MyType a1
< MyType a2
?
Комментарии:
1. Ваш
newtype
синтаксически неверен. Это, как говорится,a1 < a2
указывает на то, что а) оба имеют один и тот же тип и б) оба являются значениями, а не типами, пока мы говорим(<) :: Ord a => a -> a -> Bool
. Что вы на самом деле хотите сделать?
Ответ №1:
Поскольку сравнение с использованием стандартных Eq
классов и Ord
классов типов требует, чтобы оба сравниваемых значения имели один и тот же тип (включая параметр фантомного типа), вам необходимо либо определить свои собственные операторы сравнения, либо использовать экзистенциальную оболочку. Например:
{-# LANGUAGE ExistentialQuantification #-}
newtype MyType a = MyType { getInt :: Int }
data SomeType = forall a . SomeType (MyType a)
instance Eq SomeType where
(SomeType (MyType a)) == (SomeType (MyType b)) = a == b
instance Ord SomeType where
compare (SomeType (MyType a)) (SomeType (MyType b)) = compare a b
test = SomeType a < SomeType b where
a :: MyType Char
a = MyType 10
b :: MyType Float
b = MyType 15
Другим вариантом является use Data.Coerce
, который позволяет использовать стандартные функции сравнения без написания каких-либо шаблонных экземпляров. Вам просто нужно указать некоторые явные подписи типов:
import Data.Coerce
test2 :: Bool
test2 = coerce ((<) :: Int -> Int -> Bool) a b where
a :: MyType Char
a = MyType 10
b :: MyType Float
b = MyType 15
Комментарии:
1. На самом деле, это не отвечает на первоначальный вопрос. Первоначальная цель — каким-то образом сравнить
x :: MyType a
сy :: MyType b
по типамa
иb
сначала и только потом по значениямgetInt x
иgetInt y
. Вы только что реализовали сравнение по значениям объектов разных типов. Но ваше сравнение не является лексикографическим по отношению к типам.