我試圖很好地理解種類,類型&術語(或值,不知道哪個是正確的)以及用於操作它們的GHC擴展。我知道我們可以使用TypeFamilies來使用Types來編寫函數,現在我們也可以在一定程度上使用DataKinds,PolyKinds等操作Kinds。我已經閱讀了關於Singleton Types的這個paper,雖然我還沒有完全理解,但它似乎很有趣。這一切都讓我產生疑惑,是否有辦法創建一個函數來計算基於期限或價值水平計算的回報類型?這是依賴類型實現的嗎?作爲術語或值計算的結果返回類型
這裏的基礎上研究了很多我在想什麼
data Type1
data Type2
f :: Type1 -> Type2 -> (Type1 or Type2)--not using Either or some "wrapper" ADT
--update --------
一個例子,在這裏幫助,它現在已經成爲我清楚無論啓用了多少個擴展,函數的返回類型都不能根據Haskell中的值級別的表達式進行計算。所以我發佈了更多我的實際代碼,希望有人能幫助我決定繼續前進的最佳方式。我正在寫一個圓錐曲線和二次曲面作爲基本類型的小型庫。這些類型的操作涉及計算它們之間的交點。 2個曲面的交點是圓錐曲線類型之一,其中包括類似於點的退化(實際上除了圓錐點外,實際上還需要另一種類型的曲線,但除此之外)。確切的曲線返回類型只能由運行時相交曲面的值決定。圓柱面 - 平面相交可以導致無,線,圓或橢圓。 我的第一個計劃是使用ADT的像這樣結構曲線和曲面...
data Curve = Point !Vec3
| Line !Vec3 !UVec3
| Circle !Vec3 !UVec3 !Double
| Ellipse !Vec3 !UVec3 !UVec3 !Double !Double
| Parabola !Vec3 !UVec3 !UVec3 !Double
| Hyperbola !Vec3 !UVec3 !UVec3 !Double !Double
deriving(Show,Eq)
data Surface = Plane !Vec3 !UVec3
| Sphere !Vec3 !Double
| Cylinder !Vec3 !UVec3 !Double
| Cone !Vec3 !UVec3 !Double
deriving(Show,Eq)
...這是最直接,最具有作爲一個很好的封閉代數類型,這是我喜歡的優點。在這種表示中,交點的返回類型很簡單,只是曲線。這種表示的缺點是這些類型的每個函數都必須爲每種類型進行模式匹配,並處理所有對我來說很麻煩的排列。 Surface-Surface交叉函數將有16個模式匹配。
下一個選項是保持每個曲面和曲線類型不同。像這樣,
data Point = Point !Vec3 deriving(Show,Eq)
data Line = Line !Vec3 !UVec3 deriving(Show,Eq)
data Circle = Circle !Vec3 !UVec3 !Double deriving(Show,Eq)
data Ellipse = Ellipse !Vec3 !UVec3 !UVec3 !Double !Double deriving(Show,Eq)
data Parabola = Parabola !Vec3 !UVec3 !UVec3 !Double deriving(Show,Eq)
data Hyperbola = Hyperbola !Vec3 !UVec3 !UVec3 !Double !Double deriving(Show,Eq)
data Plane = Plane !Vec3 !UVec3 deriving(Show,Eq)
data Sphere = Sphere !Vec3 !Double deriving(Show,Eq)
data Cylinder = Cylinder !Vec3 !UVec3 !Double deriving(Show,Eq)
data Cone = Cone !Vec3 !UVec3 !Double deriving(Show,Eq)
這似乎是它可能是從長遠來看,更靈活,更是不錯,粒狀,但需要一個包裝ADT能夠從交叉功能處理多個返回類型,或建立一個一般「曲線」或「曲面」的列表,因爲它們之間沒有關係。我可以使用Type Classes和Existentials將它們分組,但是然後我失去了原來的類型,我不喜歡它。
在這些設計中的妥協使我試試這個..
---------------------------------------------------------------
-- Curve Types
---------------------------------------------------------------
type Pnte = Curve PNT
type Line = Curve LIN
type Circ = Curve CIR
type Elli = Curve ELL
type Para = Curve PAR
type Hype = Curve HYP
-----------------------------------------------
data CrvIdx = PNT
| LIN
| CIR
| ELL
| PAR
| HYP
-----------------------------------------------
data Curve :: CrvIdx → * where
Pnte :: !Vec3 → Curve PNT
Line :: !Vec3 → !UVec3 → Curve LIN
Circ :: !Vec3 → !UVec3 → !Double → Curve CIR
Elli :: !Vec3 → !UVec3 → !UVec3 → !Double → !Double → Curve ELL
Para :: !Vec3 → !UVec3 → !UVec3 → !Double → Curve PAR
Hype :: !Vec3 → !UVec3 → !UVec3 → !Double → !Double → Curve HYP
---------------------------------------------------------------
-- Surface Types
---------------------------------------------------------------
type Plne = Surface PLN
type Sphe = Surface SPH
type Cyln = Surface CYL
type Cone = Surface CNE
-----------------------------------------------
data SrfIdx = PLN
| SPH
| CYL
| CNE
-----------------------------------------------
data Surface :: SrfIdx → * where
Plne :: !Vec3 → !UVec3 → Surface PLN
Sphe :: !Vec3 → !Double → Surface SPH
Cyln :: !Vec3 → !UVec3 → !Double → Surface CYL
Cone :: !Vec3 → !UVec3 → !Double → Surface CNE
...起初我還以爲是要給我一些神奇的,兩全其美的情況,我可以指任何的曲線「(類似於列表或交集返回類型),並且還具有可用的完整類型(Curve CrvIdx),以使用多參數類型類等粒度樣式編寫函數。我很快發現這不會像我在這question中所顯示的那樣很好地工作。我頑固地繼續將我的頭靠在牆上試圖找到一種方法來編寫一個函數,該函數可以根據運行時參數的幾何屬性從我的GADT中選擇返回類型,現在認識到這不會發生。所以現在問題是什麼將是一種高效而靈活的方式來表示這些類型及其之間的相互作用?謝謝。
簡而言之,**完全**依賴類型實現的類型:類型取決於一個術語(值)。 Haskell沒有依賴類型,但Haskeller在爲常見應用程序提供等效語義方面可以非常有創意。通常涉及一個或多個這些擴展。 – 2013-02-19 07:37:26