2017-06-06 61 views
6

使用了一些扩展变量数,我可以做这样的事情:的构造方法的参数

{-# LANGUAGE GADTs #-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE DataKinds #-} 

type family TF (a :: Bool) where 
    TF 'True = Int 
    TF 'False = Double 

data D a where 
    D :: TF a -> D a 

通知构造D可以以两种方式工作。或者:

D :: Int -> D 'True 

D :: Double -> D 'False 

地使用这种模式,我可以彻底改变的参数取决于它的类型构造函数,而重新使用它的名字。

但是,我也想要参数的数量取决于它的名称。

我知道我可以用()Void替换一些参数,但我宁愿将它们全部删除。

有没有办法做到这一点?

+3

我不认为你可以用* constructor *来做这个,因为最终的codomain必须在语法上是你定义的数据类型。但是,如果你创建一个构造'D'的函数,我认为你可以通过使共域为一个类型的家族 – luqui

+1

这看起来好像会使得类型推断更加困难,而且收益甚微。您可以使用'D :: F a - > D a',其中'F'根据'a'返回不同长度的元组类型。它需要更多的拳击,但没有那么多。 – chi

+0

你为什么想这样做? –

回答

1

我不确定这是否正是@luqui在上面评论中所想到的,但是您可以在类型类中创建一个智能构造函数,该派生类的第一个参数(或任何固定数量的初始参数),以确定通过类型家庭的数量和类型的其余参数:

{-# LANGUAGE TypeFamilies #-} 

data D = Int2 Int Int 
     | Double1 Double 
     deriving (Show) 

class D1 a where 
    d :: a -> T2 a 
type family T2 a where 
    T2 Int = Int -> D 
    T2 Double = D 

instance D1 Int where 
    d x = \y -> Int2 x y  -- or just `d = Int2` 
instance D1 Double where 
    d x = Double1 x   -- or just `d = Double1` 

,其后:

> d (2 :: Int) 3 
Int2 2 3 
> d (2 :: Double) 
Double1 2.0 
> 

这不是我清楚如何将此推广到一种情况,要求有条件的调度:

data D = IntStringDouble Int String Double 
     | Int2 Int Int 
     | Double1 Double 
     deriving (Show) 

,因为你需要这样的:

T2 Int = a -> T3 a 

T3附加型家族在调度下一步,我不认为有任何方式有a的RHS型家庭是多态的。也许别人可以看到一种方式。

无论如何,这可能比它的价值更麻烦。

相关问题