我想將Haskell函數提升爲更高階的lambda微積分編碼。這幾乎是從Oleg的Typed Tagless Final編碼逐字記錄的。用於廣義多參數函數提升的類型技巧
class Lam r where
emb :: a -> r a
(^) :: r (r a -> r a) -> (r a -> r a)
lam :: (r a -> r a) -> r (r a -> r a)
instance Lam Identity where
emb = Identity
f^x = f >>= ($ x)
lam f = return (f . return =<<) -- call-by-value
eval = runIdentity
我可以嵌入任意哈斯克爾類型分爲使用emb
Lam
,但我不能使用(^)
申請即可。此外,解除職能將表現得很懶惰。相反,我必須通過應用程序解除它們的應用程序。
emb1 :: (Applicative r, Lam r)
=> (a -> b) -> r (r a -> r b)
emb1 f = lam $ \ra -> f <$> ra
emb2 :: (Applicative r, Lam r)
=> (a -> b -> c) -> r (r a -> r (r b -> r c))
emb2 f = lam $ \ra -> lam $ \rb -> f <$> ra <*> rb
emb3 :: (Applicative r, Lam r)
=> (a -> b -> c -> d)
-> r (r a -> r (r b -> r (r c -> r d)))
emb3 f = lam $ \ra -> lam $ \rb -> lam $ \rc -> f <$> ra <*> rb <*> rc
>>> eval $ emb2 (+)^emb 1^emb 2
3
雖然這是一個很多的樣板。我想創建一個通用的提升函數,可以用於任何參數函數。我覺得可以使用類似於Printf
的PrintfType
或fixed-vector
的Cont
類型的東西。我可以指定我想用型功能
type family Low h o
type instance Low () o = o
type instance Low (a, h) o = a -> Low h o
type family Lift r h o
type instance Lift r() o = o
type instance Lift r (a, h) o = r a -> r (Lift r h o)
class Emb r h o where
embed :: Low h o -> r (Lift r h o)
instance (Lam r) => Emb r() o where
embed = emb
instance (Lam r, Applicative r, Emb r h o) => Emb r (a, h) o where
embed = ?
,但我得到通過此方法非常粘,通常是由於注入的問題。我能夠通過真正可怕的newtype包裝器和範圍類型變量的組合來解決注入問題,但它從來沒有實際進行類型檢查。
這可能在Haskell中表達嗎?
我不知道答案,但下一個鏈接可能會有幫助:http://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Overview.html – wit