Во-первых, имейте в виду, что различные переменные типа уже не различимы в своей области видимости - например, если у вас есть \x y -> x
, присвоение ему сигнатуры типа a -> b -> c
приведет к ошибке о невозможности соответствия жесткимПеременные типа.Таким образом, это применимо только к чему-либо, вызывающему функцию, не позволяя ей использовать в противном случае простую полиморфную функцию таким образом, чтобы два типа были равны.Это будет работать примерно так, я предполагаю:
const' :: (a ~/~ b) => a -> b -> a
const' x _ = x
foo :: Bool
foo = const' True False -- this would be a type error
Лично я сомневаюсь, что это действительно было бы полезно - независимость переменных типа уже предотвращает свертывание универсальных функций в нечто тривиальное, зная, что два типа неравны,на самом деле не позволяет вам делать что-то интересное (в отличие от равенства, которое позволяет вам приводить между двумя типами), и такие вещи, как декларативные, а не условные, означают, что вы не можете использовать это для различения между равным / неравным как частью некоторого видаТехника специализации.
Так что, если вы имеете в виду какое-то конкретное использование, где вы этого хотите, я бы предложил попробовать другой подход.
С другой стороны, если вы просто хотите игратьс нелепым хакерством типа ...
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}
-- The following code is my own hacked modifications to Oleg's original TypeEq. Note
-- that his TypeCast class is no longer needed, being basically equivalent to ~.
data Yes = Yes deriving (Show)
data No = No deriving (Show)
class (TypeEq x y No) => (:/~) x y
instance (TypeEq x y No) => (:/~) x y
class (TypeEq' () x y b) => TypeEq x y b where
typeEq :: x -> y -> b
maybeCast :: x -> Maybe y
instance (TypeEq' () x y b) => TypeEq x y b where
typeEq x y = typeEq' () x y
maybeCast x = maybeCast' () x
class TypeEq' q x y b | q x y -> b where
typeEq' :: q -> x -> y -> b
maybeCast' :: q -> x -> Maybe y
instance (b ~ Yes) => TypeEq' () x x b where
typeEq' () _ _ = Yes
maybeCast' _ x = Just x
instance (b ~ No) => TypeEq' q x y b where
typeEq' _ _ _ = No
maybeCast' _ _ = Nothing
const' :: (a :/~ b) => a -> b -> a
const' x _ = x
Ну, это было невероятно глупо.Работает, хотя:
> const' True ()
True
> const' True False
<interactive>:0:1:
Couldn't match type `No' with `Yes'
(...)