是否有可能将不等式约束放在haskell类型变量上? [英] Is it possible to place inequality constraints on haskell type variables?

查看:154
本文介绍了是否有可能将不等式约束放在haskell类型变量上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在函数的类型变量上设置一个不等式约束,à foo ::(a〜b)=> a - > b ,如 GHC除了不平等而不是平等之外呢?



我意识到可能没有直接的方法来做到这一点(因为ghc文档没有列出任何我认识的),但是如果这种情况在某种程度上不可能,那么我会感到困惑,因为我已经接触到了所有异国情调的类型 - 福。

\xy - >> x ,给它类型签名 a - > b - > c 将产生一个关于不能匹配刚性类型变量的错误。所以这只适用于调用该函数的任何东西,从而阻止它以使两种类型相等的方式使用其他简单的多态函数。它会这样工作,我假设:

  const'::(a〜/〜b)=> a  - > b  - > a 
const'x _ = x

foo :: Bool
foo = const'True False - 这将是一个类型错误


所以,如果你有一些具体的用途在脑海中想要这个,我会建议尝试一种不同的方法。 b

另一方面,如果你只是想玩荒唐的类型hackery ...

  { - #LANGUAGE TypeFamilies# - } 
{ - #LANGUAGE TypeOperators# - }
{ - #LANGUAGE FlexibleContexts# - }
{ - #LANGUAGE FlexibleIns
{ - #语言功能依赖关系# - }
{ - #LANGUAGE MultiParamTypeClasses# - }
{ - #LANGUAGE UndecidableInstances# - }
{ - #LANGUAGE OverlappingInstances# - }

- 以下代码是我自己对Oleg原始TypeEq的黑客修改。注意
- 他的TypeCast类不再需要,基本相当于〜。

数据是=是派生(显示)
数据否=不派生(显示)

类(TypeEq x y否)=> (:/〜)x y
instance(TypeEq x y No)=> (:/〜)x y

class(TypeEq'()x y b)=> TypeEq x y b其中
typeEq :: x - > y - > b
maybeCast :: x - >也许y

实例(TypeEq'()x y b)=> TypeEq x y b其中
typeEq x y = typeEq'()x y
maybeCast x = maybeCast'()x

class TypeEq'q x y b | q x y - > b其中
typeEq':: q - > x - > y - > b
maybeCast':: q - > x - >也许y

实例(b〜是)=> 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:
与'Yes'无法匹配'No'类型
(...)


Is it possible to place an inequality constraint on the typevariables of a function, à la foo :: (a ~ b) => a -> b as in GHC type family docs, except inequality rather than equality?

I realise that there is possibly no direct way to do this (as the ghc docs doesn't list any to my knowledge), but I would be almost puzzled if this weren't in some way possible in light of all the exotic type-fu I have been exposed to.

解决方案

First, keep in mind that distinct type variables are already non-unifiable within their scope--e.g., if you have \x y -> x, giving it the type signature a -> b -> c will produce an error about not being able to match rigid type variables. So this would only apply to anything calling the function, preventing it from using an otherwise simple polymorphic function in a way that would make two types equal. It would work something like this, I assume:

const' :: (a ~/~ b) => a -> b -> a
const' x _ = x

foo :: Bool
foo = const' True False -- this would be a type error

Personally I doubt this would really be useful--the independence of type variables already prevents generic functions from collapsing to something trivial, knowing two types are unequal doesn't actually let you do anything interesting (unlike equality, which lets you coerce between the two types), and such things being declarative rather than conditional means that you couldn't use it to distinguish between equal/unequal as part of some sort of specialization technique.

So, if you have some specific use in mind where you want this, I'd suggest trying a different approach.

On the other hand, if you just want to play with ridiculous type-hackery...

{-# 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

Well, that was incredibly silly. Works, though:

> const' True ()
True
> const' True False

<interactive>:0:1:
    Couldn't match type `No' with `Yes'
    (...)

这篇关于是否有可能将不等式约束放在haskell类型变量上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆