簡體   English   中英

我怎樣才能從Control.Lens中使(Fold sa)成為一個半身像?

[英]How can I make (Fold s a) from Control.Lens a monoid?

我在耍鏡頭和棱鏡,到處都是雜草。 我想在模板Haskell中編寫以下內容,但它無法編譯:

data Suit = Spade | Heart | Diamond | Club
makePrisms ''Suit
blackSuits = _Spade <> _Club

我對鏡頭和棱鏡的所有了解(以及Getter文檔中的注釋)都表明_Spade <> _Club應該是有效的Fold Suit () 但是ghc無法編譯以上代碼; 它抱怨幾個模棱兩可的實例。 ghci為_Spade <> _Club提供了以下類型簽名:

_Spade <> _Club
  :: (Applicative f, Monoid (p Suit (f Suit)), Choice p) =>
     p () (f ()) -> p Suit (f Suit)

通過將p替換為(->)我可以將該類型放寬為

(Applicative f, Monoid (f Suit)) => (() -> f ()) -> Suit -> f Suit

那和Fold Suit ()之間的唯一區別是后者具有(Applicative f, Contravariant f) => ...而不是Monoid (f Suit)限制。 當我閱讀Contravariant我看到斷言(Applicative f, Contravariant f)共同暗示f對於某些類半體r實際上是Const r r 這似乎表明上述類型實際上是Fold Suit ()的子集。 但是當我嘗試將blackSuits :: Fold Suit ()到我的代碼中時,我得到了

Could not deduce (Monoid (f Suit)) arising from a use of ‘<>’
from the context (Contravariant f, Applicative f) ...

如果我只是嘗試在折痕上定義mono半體而不是從棱鏡開始,則會遇到類似的錯誤。 我沒有做任何嘗試使Fold sa a Monoid通過編譯器。 有什么辦法可以使這項工作嗎?

如果您查看Fold簽名:

type Fold s a = forall f. (Contravariant f, Applicative f)=> (a -> f a) -> s -> f s

它說它必須對所有ContravariantApplicative f Contravariant 當使用<>將兩個折疊組合在一起時,函數instance Semigroup b => Semigroup (a -> b)Semigroup實例要求fsSemigroup 這意味着它將不再將check輸入為Fold 然而,大多數(?全部)函數使用倍lens還是會接受這一點,因為他們采取了Getting rsa = (a -> Const ra) -> s -> Const rs ,這這將類型檢查的。

您可以做幾件事。 您可以使用具有自己的Monoid實例的Fold類型:

> :set -XTemplateHaskell
> import Control.Lens
> import Data.Semigroup
> data Suit = Spade | Heart | Diamond | Club; makePrisms ''Suit
> let blackSuitsFold = runFold $ Fold _Spade <> Fold _Club :: Fold Suit ()

或者您可以“克隆”折疊:

> let cloneFold = foldring . foldrOf
> let blackSuitsClone = cloneFold $ _Spade <> _Club :: Fold Suit ()

或者,如果您不需要將其Fold ,則可以使用“ Getting同義詞,在大多數情況下它的作用相同:

> let blackSuitsGetter = _Spade `mappend` _Club :: Monoid r => Getting r Suit ()
> has blackSuitsGetter Spade
True

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM