也許有更好的方法來實作我想要的東西,但這是我目前的嘗試。
我正在使用 singletons 包,以便將值重化為型別。這樣做很好,但是在某些時候,我將不得不運行一個在重化型別中具有多型性的函式,并期望它有一個Typeable實體。當然,Haskell中的所有型別都有這樣的實體(至少Afaik?),但由于型別變數在編譯時是未知的,所以型別檢查器無法找到這樣的實體。讓我來說明一下:
{-# LANGUAGE GADTs, FlexibleInstances, RankNTypes, PolyKinds, TypeFamilyDependencies, InstanceSigs #-}
import Data.ByteString (ByteString)
import Data.Typeable (Typeable)
import Data.Singletons (Typeable)
data EType
= Integer Integer
| Boolean = Boolean
| ByteStr
deriving (Eq, Ord, Show, Read)
--對應的單子型別。
-- 注意,引數捎帶著。
-- 關于Haskell的常規型別。
data SType a where
SInteger :: SType Int
SBoolean :: SType Bool BoolSByteStr :: SType ByteString ByteString--我的單子型別是單子。
type instance Sing = SType
-- 使得將`EType`重化為`Int`成為可能,。
-- `Bool'和`ByteString',并能反映出來。
-- 從它們到`EType`。
instance SingKind * where
type Demote * = EType
-- SType a -> EType
fromSing :: Sing (a :: *) -> Demote *
fromSing SInteger=Integer
fromSing SBoolean = Boolean
fromSing SByteStr = ByteStr
-- EType -> SomeSing *
toSing :: Demote * -> SomeSing *
toSing Integer = SomeSing SInteger *.
toSing Boolean = SomeSing SBoolean ByteStr = SomeSing SByteStr
--一些假的型別用于說明。
-- 應該是不言而喻的。
data UntypedExp
data Exp a
data Result
--我真正想要實作的功能。
checkResult :: EType -> UntypedExp -> Maybe Result >。
checkResult typ expr = withSomeSing typ $ singType ->
makeResult singType <$> inferExpr expr
-- 我的主要型別檢查函式的一個版本(一些)。
-- 省略了輸入)。) 呼叫者選擇`a`,然后
--取決于輸入是否可以被輸入。
-- 這樣的話,我們回傳`Just e`或`Nothing`。
-- 這已經被實施了。。
inferExpr :: Typeable a => UntypedExp -> Maybe (Exp a)
inferExpr = undefined
-- 根據`a`,這個函式需要做的是
-- 不同的事情來構建一個`Result`。
-- 因此要重化。
-- 這是已經實作的。 -- 這是已經實作的。
makeResult :: Sing a -> Exp a -> Result ::.
makeResult = undefined
這給了我一個錯誤
這給了我一個錯誤。
- No instance for (Typeable a) arising from a useof 'inferExpr'
- 在第二個引數的'(<$>)',即'inferExpr expr'
在運算式: makeResult singType <$> inferExpr expr
在第二個引數的'($)',即
'singType -> makeResult singType <$> inferExpr expr'
|
54 | makeResult singType <$> inferExpr expr
| ^^^^^^^^^^^^^^
這是很有意義的。withSomeSing并不能保證傳遞給continuation的Sing a滿足Typeable a。
我可以通過隱藏Data.Singleton的一些匯入來解決這個問題,而是用相關的約束條件來定義我自己的版本:
import Data.Singleton? Singletons hiding (SomeSing,SingKind(.),withSomeSing)
withSomeSing :: forall k r
. SingKind k.
=> Demote k
-> (forall (a :: k) 。Typeable a => Sing a -> r)
-> r
withSomeSing x f =
case toSing x of
SomeSing x' -> f x'
class SingKind k where<
type Demote k = (r :: *) | r -> k
fromSing :: Sing (a :: k) -> Demote k
toSing :: Demote k -> SomeSing k
data SomeSing k where
SomeSing :: Typeable a => Sing (a :: k) -> SomeSing k
這使一切都正常,但感覺是絕對糟糕的風格。
因此我的問題是:有沒有辦法匯入SomeSing和withSomeSing的原始定義,但用這個額外的約束來增強它們的型別?或者,你建議如何以更好的方式來解決這個問題呢?
uj5u.com熱心網友回復:
我想到兩個選擇:
實施
withTypeable :: SType a -> (Typeable a => r) -> r通過對第一個引數進行詳盡的模式匹配。然后,你不只是使用
withSomeSing,而是同時使用,如withSomeSing typ $ singType -> withTypeable singType $ ...。升級你的
Sing實體。撰寫data STypeable a where STypeable : 。Typeable a => SType a -> STypeable a type instance Sing = STypeable你將需要在
toSing和fromSing的每個分支中拋出一個額外的STypeable建構式。然后你可以在withSomeSing中進行模式匹配,如withSomeSing $ (STypeable singType) -> ...。
也可能有其他的方法。
uj5u.com熱心網友回復:
你可以完全避免使用CPS風格。任何時候我看到(Cls a => res) -> res,我更喜歡使用模式匹配。
singletons有pattern FromSing,它用模式匹配取代了withSomeSing:
checkResult :: EType -> UntypedExp -> Maybe Result
checkResult (FromSing (singType :: SType a) ) expr = .
然后你定義一種方法來從SType中獲得一個Typeable約束條件。為了這些目的,你對一個型別索引的TypeRep進行模式匹配,從Type.Reflection。pattern FromSing和pattern TypeRep最近被添加進來,不要與TypeRep型別建構式混淆,所以檢查一下你是否有最新的版本。
pattern STypeRep :: () => Typeable a => stype a
pattern STypeRep <- (stypeRep -> TypeRep)
--其中STypeRep = stype typeRep。
stypeRep :: SType a -> TypeRep a
stypeRep = case >。
SInteger -> typeRep
SBoolean -> typeRep
SByteStr -> typeRep
--實際上是可選的和部分的。
-- stype :: forall a. TypeRep a -> SType a
-- stype rep
-- | Just HRefl <- eqTypeRep rep (typeRep @Int)
-- = SInteger。
-- | Just HRefl <- eqTypeRep rep (typeRep @Bool) >。
-- = SBoolean
-- | Just HRefl <- eqTypeRep rep (typeRep @ByteString)
-- = SByteStr
-- | let
-- = error "crash and burn"
最終形式:
checkResult :: EType -> UntypedExp -> Maybe Result
checkResult (FromSing singType@STypeRep) = fmap (makeResult singType) . InferExpr
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/316911.html
標籤:
