异构列表/HList l -> [e]?
Heterogeneous list / HList l -> [e]?
感谢您回答我的另一个问题 -
, I could start using HList: Heterogeneous lists, mostly with API of https://hackage.haskell.org/package/HList-0.5.2.0/docs/Data-HList-HList.html
现在,我想要 - producing homogenous lists 作为 HList l -> [e]
hMapOut :: forall f e l. HMapOut f l e => f -> HList l -> [e]
我一直在尝试创建自己的概念验证代码,但不知道如何正确地进行。
import Data.HList (HList, hBuild, hEnd, hMap, hMapOut)
iA :: [Int]
iA = [1, 2, 3] :: [Int]
iB :: [[Char]]
iB = ["foo", "bar"] :: [[Char]]
iAiB :: HList '[[Int], [[Char]]]
iAiB = hEnd $ hBuild iA iB
flag :: Any -> Bool
flag = \iX -> length iX >= 3 --- ERROR HERE
flags :: HList l -> [e]
flags = \iList ->
iList & hMapOut flag
iBool :: [e]
iBool = flags iAiB
main :: IO ()
main = print iBool
这是最简单的示例,为了我的目的,它需要被包装到 IO
中,无论哪种方式,它都有相同的错误。
• Couldn't match expected type ‘t0 a0’ with actual type ‘Any’
• In the first argument of ‘length’, namely ‘x’
In the first argument of ‘(>=)’, namely ‘length x’
In the expression: length x >= 3 typecheck(-Wdeferred-type-errors)
我想Any
打错了,但我不知道怎么打。有什么建议?
我也做了
flag :: forall (t :: * -> *) a. Foldable t => t a -> Bool
flag = \iX -> length iX >= 3
这消除了此函数的错误,但现在
上的另一个错误
flags :: HList l -> [e]
flags = \iList ->
iList & hMapOut flag --- ERROR HERE
作为
• Ambiguous type variables ‘t0’,
‘a0’ arising from a use of ‘hMapOut’
prevents the constraint ‘(Data.HList.HList.HFoldr
所以,这似乎是根本问题。
尝试过Fun'
import Data.HList (HList, hBuild, hEnd, hMap, hMapOut, Fun' (Fun'))
flags :: HList l -> [e]
flags = \iList ->
iList & hMapOut (Fun' flag :: Fun' Foldable Bool)
错误:
• Could not deduce: b ~ Bool
from the context: Data.HList.FakePrelude.FunCxt Foldable b
bound by a type expected by the context:
forall b.
Data.HList.FakePrelude.FunCxt Foldable b =>
Data.HList.FakePrelude.FunApp Bool b -> b
您的第二个版本 flag :: ∀ t a. Foldable t => t a -> Bool
是明智的。但是将其映射到 HList 上有点棘手,因为约束没有 Type -> Constraint
的形式,而是 t
与 (Type -> Type) -> Constraint
.
的应用
由于您似乎不需要支持通用的可折叠容器(并且 FWIW Foldable
基于 length
的定义是 ) I'd suggest instead using the IsList
class:
flag :: ∀ l. IsList l => l -> Bool
flag = (>=3) . length . toList
或者,我们可以使用 Type -> Constraint
签名快速将 Foldable
包装到我们自己的 class 中:
class HasLength l where gLength :: l -> Int
instance Foldable t => HasLength (t a) where gLength = length
flag :: ∀ l. HasLength l => l -> Bool
flag = (>=3) . gLength
现在折叠 HList 很容易了:
flags :: HMapOut (Fun IsList Bool) l Bool
=> HList l -> [Bool]
flags = hMapOut (Fun flag :: Fun IsList Bool)
请注意,这是 Fun
,而不是 Fun'
。后者在这种情况下不起作用(通常使用 HMapOut
),因为该函数在其 输入 中是多态的,即无法确定输入从输出中键入。
同样,我倾向于定义一个助手来使这种定义更方便:
h'MapOut :: ∀ (cxt :: Type -> Constraint) getb l
. HMapOut (Fun cxt getb) l getb
=> (∀ a . (cxt a) => a -> getb) -> HList l -> [getb]
h'MapOut f = hMapOut (Fun f :: Fun cxt getb)
然后简单地
flags = h'MapOut @IsList flag
完整代码:
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax
, KindSignatures, ConstraintKinds, RankNTypes
, FlexibleContexts, FlexibleInstances
, AllowAmbiguousTypes, TypeApplications #-}
import Data.HList
import GHC.Exts (IsList(..))
import Data.Kind
flag :: ∀ l. HasLength l => l -> Bool
flag = (>=3) . gLength
h'MapOut :: ∀ (cxt :: Type -> Constraint) getb l
. HMapOut (Fun cxt getb) l getb
=> (∀ a . (cxt a) => a -> getb) -> HList l -> [getb]
h'MapOut f = hMapOut (Fun f :: Fun cxt getb)
flags :: HMapOut (Fun HasLength Bool) l Bool
=> HList l -> [Bool]
flags = h'MapOut @HasLength flag
class HasLength l where gLength :: l -> Int
instance Foldable t => HasLength (t a) where gLength = length
感谢您回答我的另一个问题 -
现在,我想要 - producing homogenous lists 作为 HList l -> [e]
hMapOut :: forall f e l. HMapOut f l e => f -> HList l -> [e]
我一直在尝试创建自己的概念验证代码,但不知道如何正确地进行。
import Data.HList (HList, hBuild, hEnd, hMap, hMapOut)
iA :: [Int]
iA = [1, 2, 3] :: [Int]
iB :: [[Char]]
iB = ["foo", "bar"] :: [[Char]]
iAiB :: HList '[[Int], [[Char]]]
iAiB = hEnd $ hBuild iA iB
flag :: Any -> Bool
flag = \iX -> length iX >= 3 --- ERROR HERE
flags :: HList l -> [e]
flags = \iList ->
iList & hMapOut flag
iBool :: [e]
iBool = flags iAiB
main :: IO ()
main = print iBool
这是最简单的示例,为了我的目的,它需要被包装到 IO
中,无论哪种方式,它都有相同的错误。
• Couldn't match expected type ‘t0 a0’ with actual type ‘Any’
• In the first argument of ‘length’, namely ‘x’
In the first argument of ‘(>=)’, namely ‘length x’
In the expression: length x >= 3 typecheck(-Wdeferred-type-errors)
我想Any
打错了,但我不知道怎么打。有什么建议?
我也做了
flag :: forall (t :: * -> *) a. Foldable t => t a -> Bool
flag = \iX -> length iX >= 3
这消除了此函数的错误,但现在
上的另一个错误flags :: HList l -> [e]
flags = \iList ->
iList & hMapOut flag --- ERROR HERE
作为
• Ambiguous type variables ‘t0’,
‘a0’ arising from a use of ‘hMapOut’
prevents the constraint ‘(Data.HList.HList.HFoldr
所以,这似乎是根本问题。
尝试过Fun'
import Data.HList (HList, hBuild, hEnd, hMap, hMapOut, Fun' (Fun'))
flags :: HList l -> [e]
flags = \iList ->
iList & hMapOut (Fun' flag :: Fun' Foldable Bool)
错误:
• Could not deduce: b ~ Bool
from the context: Data.HList.FakePrelude.FunCxt Foldable b
bound by a type expected by the context:
forall b.
Data.HList.FakePrelude.FunCxt Foldable b =>
Data.HList.FakePrelude.FunApp Bool b -> b
您的第二个版本 flag :: ∀ t a. Foldable t => t a -> Bool
是明智的。但是将其映射到 HList 上有点棘手,因为约束没有 Type -> Constraint
的形式,而是 t
与 (Type -> Type) -> Constraint
.
由于您似乎不需要支持通用的可折叠容器(并且 FWIW Foldable
基于 length
的定义是 IsList
class:
flag :: ∀ l. IsList l => l -> Bool
flag = (>=3) . length . toList
或者,我们可以使用 Type -> Constraint
签名快速将 Foldable
包装到我们自己的 class 中:
class HasLength l where gLength :: l -> Int
instance Foldable t => HasLength (t a) where gLength = length
flag :: ∀ l. HasLength l => l -> Bool
flag = (>=3) . gLength
现在折叠 HList 很容易了:
flags :: HMapOut (Fun IsList Bool) l Bool
=> HList l -> [Bool]
flags = hMapOut (Fun flag :: Fun IsList Bool)
请注意,这是 Fun
,而不是 Fun'
。后者在这种情况下不起作用(通常使用 HMapOut
),因为该函数在其 输入 中是多态的,即无法确定输入从输出中键入。
同样,我倾向于定义一个助手来使这种定义更方便:
h'MapOut :: ∀ (cxt :: Type -> Constraint) getb l
. HMapOut (Fun cxt getb) l getb
=> (∀ a . (cxt a) => a -> getb) -> HList l -> [getb]
h'MapOut f = hMapOut (Fun f :: Fun cxt getb)
然后简单地
flags = h'MapOut @IsList flag
完整代码:
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax
, KindSignatures, ConstraintKinds, RankNTypes
, FlexibleContexts, FlexibleInstances
, AllowAmbiguousTypes, TypeApplications #-}
import Data.HList
import GHC.Exts (IsList(..))
import Data.Kind
flag :: ∀ l. HasLength l => l -> Bool
flag = (>=3) . gLength
h'MapOut :: ∀ (cxt :: Type -> Constraint) getb l
. HMapOut (Fun cxt getb) l getb
=> (∀ a . (cxt a) => a -> getb) -> HList l -> [getb]
h'MapOut f = hMapOut (Fun f :: Fun cxt getb)
flags :: HMapOut (Fun HasLength Bool) l Bool
=> HList l -> [Bool]
flags = h'MapOut @HasLength flag
class HasLength l where gLength :: l -> Int
instance Foldable t => HasLength (t a) where gLength = length