重叠/不连续的封闭类型族

我一直在玩一些封闭类型的家庭,但是我总觉得事物往往不适用于Num而没有指定类型。

这是一个例子。

{-# LANGUAGE FlexibleInstances         #-}
{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE TypeFamilies              #-}
{-# LANGUAGE DataKinds                 #-}
{-# LANGUAGE UndecidableInstances      #-}
{-# LANGUAGE OverlappingInstances      #-}
{-# LANGUAGE IncoherentInstances       #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
module Main where

import Data.Typeable

type family UnMaybed a where
    UnMaybed (Maybe a) = a
    UnMaybed a = a

class UnMaybe x where
    unMaybe :: x -> UnMaybed x

instance UnMaybe (Maybe a) where
    unMaybe (Just a) = a

instance (UnMaybed a ~ a) => UnMaybe a where
    unMaybe a = a

main = do
    print $ unMaybe 'c'
    print $ unMaybe (1::Int)
    print $ unMaybe (Just 1)
    print $ unMaybe 1 -- this line does not compile

除最后一行之外的所有内容都将被编译

../Example.hs:23:17:
    Occurs check: cannot construct the infinite type: s0 ~ UnMaybed s0
    The type variable ‘s0’ is ambiguous
    In the second argument of ‘($)’, namely ‘unMaybe 1’
    In a stmt of a 'do' block: print $ unMaybe 1

现在我知道这是因为数字是多态的,并且( Maybe a )可能是Num一个实例。 我认为对于正常重叠的类型类,这个困境可以通过使用IncoherentInstances PRAGMA来解决。 无论如何,我想问问是否有办法在类型家庭中完成这项工作?

我也想过在UnMaybed明确指定Num

type family UnMaybed a where
    unMaybed (Num a => a) = a
    UnMaybed (Maybe a) = a
    UnMaybed a = a

这编译,但我认为第一个案件永远不会匹配这可能是一个错误。


回答:http://www.haskell.org/pipermail/haskell-cafe/2014-March/113153.html

这是封闭式家庭的限制,但限制是有充分理由的。

IncoherentInstances威胁类型实例的一致性,这意味着即使对于相同的<<some type>> ,在不同地方可能会以不同的方式实现一个约束UnMaybe <<some type>> <<some type>> 。 但是,类型实例选择纯粹是一种运行时行为效应。 选择不同的实例不会影响程序中的类型。

另一方面,类型家族直接影响类型。 允许像IncoherentInstances工作方式一样的不连贯性可以用来实现unsafeCoerce。

没有类型签名,没有太多的方法。 (一种可能性是基本上使用RebindableSyntax来禁用数字重载,但这是一个大锤子。)

最后一个例子(使用UnMaybed(Num a => a))甚至编译的事实是一个很快就会出现的错误。

修订

我发现你可以实际实现这个功能,而不需要像下面这样输入系列。

{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances      #-}
{-# LANGUAGE IncoherentInstances       #-}
{-# LANGUAGE TypeFamilies #-}
module Main where

class UnMaybe x y where
    unMaybe :: x -> y

instance (a~a') => UnMaybe (Maybe a) a' where
    unMaybe (Just a) = a

instance (a~a') => UnMaybe a a' where
    unMaybe a = a

请注意,由于等式约束,您仍然需要类型族扩展。

链接地址: http://www.djcxy.com/p/78247.html

上一篇: overlapping/Incoherent closed type families

下一篇: 'type family' vs 'data family', in brief?