2017-06-06 95 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型家庭是多態的。也許別人可以看到一種方式。

無論如何,這可能比它的價值更麻煩。

相關問題