我最近定義了一個我可能無法計算其欄位的型別:
data Foo = Foo {x, y :: Int, others :: NonEmpty Int}
data Input
computeX, computeY :: Input -> Maybe Int
computeOthers :: Input -> Maybe (NonEmpty Int)
現在,我可能會做的一件顯而易見的事情就是使用liftA3:
foo :: Input -> Maybe Foo
foo i = liftA3 Foo (computeX i) (computeY i) (computeOthers i)
這作業得很好,但我認為Foo將Maybes概括為持有s ,然后將一種型別轉換Foo為另一種型別可能會很有趣。在一些類似的情況下,我可以給Foo型別一個型別引數并派生 Traversable。然后在創建 a 之后Foo (Maybe Int),我可以使用sequenceA :: Foo (Maybe Int) -> Maybe (Foo Int). 但這在這里不起作用,因為我的函式沒有給我一個NonEmpty (Maybe Int),它給了我一個Maybe (NonEmpty Int).
所以我想我會嘗試通過函子引數化:
data Foo f = Foo {x, y :: f Int, others :: f (NonEmpty Int)}
但問題是,我如何將 aFoo Maybe變成 a Maybe (Foo Identity)?顯然我可以手動撰寫該函式:它與liftA3上面的內容同構。但是對于這種高階型別是否有一些平行的 Traversable ,以便我可以對這個問題應用更通用的函式,而不是用定制的函式重新做它?
uj5u.com熱心網友回復:
此類資料型別稱為“高級資料”(HKD)。操作它們通常是通過泛型或模板 Haskell 完成的。
有類似的庫higgledy為 HKD 提供內置功能。我相信construct是您正在尋找的功能:
{-# LANGUAGE DeriveGeneric #-}
import Data.Generic.HKD
import GHC.Generics
import Data.Monoid
data Foo = Foo { x, y :: Int, z :: [Int] }
deriving (Generic, Show)
emptyFoo :: HKD Foo Last
emptyFoo = mempty
sampleFoo :: HKD Foo Last
sampleFoo = deconstruct (Foo 1 2 [3])
emptyFoo' :: Last Foo
emptyFoo' = construct emptyFoo
sampleFoo' :: Last Foo
sampleFoo' = construct sampleFoo
main = do
print emptyFoo'
print sampleFoo'
這將列印:
Last {getLast = Nothing}
Last {getLast = Just (Foo {x = 1, y = 2, z = [3])}
編輯:我剛剛發現一個更受歡迎的圖書館是barbies(higgledy 也取決于芭比娃娃)。您正在尋找的函式也作為以下應用程式出現在該庫中btraverse:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.List.NonEmpty
import Barbies
import GHC.Generics
import Data.Functor.Identity
data Foo f = Foo {x, y :: f Int, others :: f (NonEmpty Int)}
deriving (Generic, FunctorB, TraversableB, ConstraintsB)
deriving instance AllBF Show f Foo => Show (Foo f)
f :: Applicative f => Foo f -> f (Foo Identity)
f = btraverse (fmap Identity)
main :: IO ()
main = do
print (f (Foo (Just 1) (Just 2) (Just (3 :| []))))
這列印:
Just (Foo {x = Identity 1, y = Identity 2, others = Identity (3 :| [])})
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/387040.html
