我正試圖弄清楚異質集合,有一些型別檢查的問題我無法理解。
data HTypeMap (f : : * -> *)(types :: [*])where
HNil :: HTypeMap f '[] 。
HCons :: f e -> HTypeMap f types -> HTypeMap f (e ': types)
(它基本上應該是一個從型別到該型別的值的映射,在一些漏斗f下)。例如:
testMap :: HTypeMap Prelude.Maybe '[Prelude。 Int, Prelude.String]
testMap = HCons (Prelude. Just 3) (HCons (Prelude.Just "Hello" />) HNil)
我一直試圖制定一個函式,讓我在知道我的集合中的所有型別都是受限制的情況下運行一個map,要像這樣使用:
showEverything :: AllConstrained Show types => HTypeMap f types -> [String ]
showEverything = mapConstrained show
type family AllConstrained (c :: u -> Constraint) (ts :: [u]) :: Constraint where
AllConstrained c ' [] = ()
AllConstrained c (t ': ts) = (c t, AllConstrained c ts)
到目前為止,我的嘗試:
我的嘗試是
- 只是一個簡單的函式... GHC不會讓我寫這個型別:
mapConstrained :: AllConstrained c types => (forall t. c t => f t -> a) -> HTypeMap f types -> [a]
mapConstrained = _
它說:
- Could不推導。AllConstrained c0 types
從背景關系中。AllConstrained c型別
我完全不明白這一點...... 我只有一個約束被考慮在那里,它是c。(我有ScopedTypeVariables)
相同風格的型別類也是如此...... 這里有某種我沒有注意到的歧義......
2.
2.
這個不方便的方法實際上是可行的:
這個不方便的方法實際上是可行的:
data ContraintRunnerF f c r = ContraintRunnerF {runMeF : : forall x. c x => f x -> r}。
class MapConstrained c types where>
mapConstrained :: forall a f r. AllConstrained c types => ContraintRunnerF f c r -> HTypeMap f types -> [r]
instance MapConstrained c '[] where<
mapConstrained _ HNil = [] 。
instance MapConstrained c types => MapConstrained c (t ' 。types) where
mapConstrained g (HCons e rest) = (runMeF g e) : mapConstrained @c g rest
像這樣使用:
showRunnerF :: ContraintRunnerF Prelude.Identity Prelude。 Show Prelude.String。
showRunnerF = ContraintRunnerF Prelude.show
showRunnerFM :: ContraintRunnerF Prelude.Maybe Prelude。 Show Prelude.String。
showRunnerFM = ContraintRunnerF Prelude.show
testMap :: HTypeMap Prelude.Maybe '[Prelude。 Int, Prelude.String]
testMap = HCons (Prelude. Just 3) (HCons (Prelude.Just "Hello" />) HNil)
test1 :: [Prelude.String]
test1 = mapConstrained showRunnerFM testMap
但不幸的是,即使是簡單的替換也不能進行型別檢查,基本上需要我指定所有的型別:
test2 :: [Prelude.String]
test2 = mapConstrained (ContraintRunnerF Prelude.show) testMap
- Could not deduce: (c0 Prelude.Int, c0 [Prelude.Char] )
產生于使用of'mapConstrained'。
所以,問題是:
uj5u.com熱心網友回復:
型別變數c在mapConstrained的型別中被稱為ambiguous,因為從來沒有任何方法可以從它的引數中確定該型別變數應該是什么。
這個問題的解決方案是TypeApplications,它允許你為一個模糊的型別變數明確指定一個型別。
{-# LANGUAGE AllowAmbiguousTypes, TypeApplications, PolyKinds #-}
import Data.Kind
data HTypeMap (f :: * -> *) (types : : [*]) where
HNil :: HTypeMap f '[] 。
HCons :: f e -> HTypeMap f types -> HTypeMap f (e ': types)
type family AllConstrained (c :: u -> Constraint) (ts :: [u]) :: Constraint where
AllConstrained c ' [] = ()
AllConstrained c (t ': ts) = (c t, AllConstrained c ts)
mapConstrained :: AllConstrained c types => (forall t. c t => f t -> a) -> HTypeMap f types -> [a] 。
mapConstrained _ _ = undefined
testMap :: HTypeMap Prelude.Maybe '[Prelude。 Int, Prelude.String]
testMap = HCons (Prelude. Just 3) (HCons (Prelude.Just "Hello" />) HNil)
--注意這里`@Show'是型別應用--它在型別級別應用`mapConstrained'。
test = mapConstrained @Show show testMap
在第二種情況下,你必須再一次明確地指定型別變數:
test2 :: [Prelude.String]
test2 = mapConstrained (ContraintRunnerF @_ @Show Prelude.show) testMap
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/316960.html
標籤:
上一篇:如何將Data.Text.Internal.Text轉換為Data.ByteString.Lazy.Bytestring(文本轉換為LazyBytestring)?
下一篇:實體約束比較型別-家族約束
