Как сравнивать экземпляры фантомного типа по отношению к аргументу фантомного типа?

#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 . Вы только что реализовали сравнение по значениям объектов разных типов. Но ваше сравнение не является лексикографическим по отношению к типам.