如何摆脱可能多余的功能约束?

Gsp*_*pia 0 haskell

让我们有两个没有任何方法的类,另一个是子类.此外,假设功能f5f6那些unsafeCoerce从类型等.

现在,ghci可以组合这些函数并找到它们的签名(在ScopedTypeVariables的帮助下),见f56, f56b and f56'下文.这些本质上是具有约束的函数Hmm.

  1. 是否可以编写f56c,即在没有引用SHmm约束中的类的情况下编写它?例如,ghci可以在一些language-pragma的帮助下编译吗?

  2. unsafeCoerce当班级没有任何方法时,使用会有什么样的危险?(或者当子类SHmm 没有任何方法?)有没有写别的办法/推荐的方式f5f6

作为最后一个,在下面的代码中f5,f6有他们的签名,为什么不可能只写f56 = f5 . f6?(特别是在SHmm空的情况下,这就是SHmm在编写时很容易认为不需要约束的原因f56.)

{-# LANGUAGE ScopedTypeVariables, KindSignatures, MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes, FlexibleInstances, FlexibleContexts #-}
{-# LANGUAGE AllowAmbiguousTypes #-}

import Unsafe.Coerce

class Hmm (f :: *)
class Hmm f => SHmm f

f5 :: (Hmm m1, SHmm m) => m -> m1
f5 = unsafeCoerce

f6 :: (Hmm m, SHmm m1) => m -> m1
f6 = unsafeCoerce

f56 :: forall m1 m2 m3. (Hmm m3, Hmm m2, SHmm m1) => m3 -> m2
f56 = f5 . (f6 :: m3 -> m1)

f56b :: forall m1 m2. (Hmm m2, SHmm m1) => m2 -> m2
f56b = f5 . (f6 :: m2 -> m1)

-- f56c :: forall m2. Hmm m2 => m2 -> m2
-- f56c = f5 . (f6 :: SHmm m1 => m2 -> m1)

f56' :: forall m1 m2 m3. (Hmm m3, Hmm m2, SHmm m1) => m3 -> m2
f56' a = f5 $ (f6 :: m3 -> m1) a
Run Code Online (Sandbox Code Playgroud)

lef*_*out 5

绝对不是一个安全使用unsafeCoerce.基本上,f5只要每个类型都有某个类的实例,就可以通过签名将任意两种类型转换为另一种类型.但是知道这并没有告诉你关于类型和类型之间关系的任何信息.唯一可以安全的方法是,如果只有一个类型带有一个实例 - 比如说- 因为那样它实际上就是这样mm1HmmInt

f5 :: (m1 ~ Int, m ~ Int) => m -> m1
Run Code Online (Sandbox Code Playgroud)

又名

f5 :: Int -> Int
f5 = unsafeCoerce
Run Code Online (Sandbox Code Playgroud)

......事实上这确保有效,尽管显然不是很有用.但是,只要你添加任何其他实例,SHmm String你就会在Int和之间得到一个完整的虚假"转换函数" String.

这里的类HmmSHmm任何方法是否无关紧要,除非它的方法只能实现同构类型Void(在这种情况下所有这些函数都是安全的,但也完全荒谬).

因此,作为开始工作f5f6不工作,我不知道如何回答其余部分.即使在概念层面,我也看不出这有什么意义.