我想使用HList: Heterogeneous lists。
安裝庫然后import Data.HList (HList)到目前為止已經完成。
現在調查https://bitbucket.org/HList/hlist/src/master/examples/HListExample/并不能幫助我開始撰寫代碼。
我想做的是,
創建一個 hello-world 異構串列,例如
H[1, "2"](完全不確定語法)將異構串列映射到
print每個串列。
有沒有人熟悉如何使用HList?
uj5u.com熱心網友回復:
您可以使用hEndandhBuild函式構造 HList,例如:
hello = hEnd (hBuild 1 "2")
映射print此串列要困難得多。我認為沒有簡單的方法可以撰寫能夠映射print到 HList 的高階函式,但是您可以像這樣手動遍歷 HList:
{-# LANGUAGE DataKinds #-}
import Data.HList
class PrintEach ts where
printEach :: HList ts -> IO ()
instance PrintEach '[] where
printEach HNil = pure ()
instance (Show t, PrintEach ts) => PrintEach (t : ts) where
printEach (HCons x xs) = print x *> printEach xs
hello = hEnd (hBuild 1 "2")
main = printEach hello
-- This prints:
-- 1
-- "2"
uj5u.com熱心網友回復:
您可能不想只映射HList,而是遍歷它,也就是mapM. 而且您可能對個別結果不感興趣,()而只對副作用感興趣,所以那時會這樣mapM_。
HList 確實有一個通用工具,不出所料地稱為hMapM_。將它與任意受約束的多型函式一起使用有點涉及,但對于列印來說,這實際上是隨庫一起提供的:
Prelude Data.HList> let l = 1.*."2".*.HNil :: HList '[Int, String]
Prelude Data.HList> l
H[1,"2"]
Prelude Data.HList> hMapM_ HPrint l
1
"2"
正如 Noughtmare 評論的那樣,將其與其他多型函式(無需撰寫自定義型別)一起使用的方法是使用Fun,例如
Prelude Data.HList> hMapM_ (Fun print :: Fun Show (IO ())) l
1
"2"
...這不是太尷尬,但仍然有點煩人。我會定義一個同義詞,允許用 TypeApplications 撰寫它以避免冗余:
{-# LANGUAGE TypeFamilies, RankNTypes, ConstraintKinds, UnicodeSyntax #-}
import Data.Kind
fun :: ? (cxt :: Type -> Constraint) getb
. (? a. (cxt a) => a -> getb) -> Fun cxt getb
fun = Fun
然后
Prelude Data.HList Data.Kind> :set -XTypeApplications
Prelude Data.HList Data.Kind> hMapM_ (fun @Show print) l
1
"2"
或者我們甚至可以做到
{-# LANGUAGE FlexibleContexts, AllowAmbiguousTypes #-}
h'MapM_ :: ? (cxt :: Type -> Constraint) l m
. (Monad m, HFoldr (Mapcar (Fun cxt (m ()))) [m ()] l [m ()])
=> (? a. (cxt a) => a -> m ()) -> HList l -> m ()
h'MapM_ f = hMapM_ (Fun f :: Fun cxt (m ()))
然后
Prelude Data.HList Data.Kind> h'MapM_ @Show print l
1
"2"
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/435554.html
標籤:哈斯克尔
