簡體   English   中英

如何在Haskell中獲得深層函子的句柄?

[英]How do I get a handle on deep stacks of functors in Haskell?

偶爾我會發現自己映射到一大堆仿函數,例如一些可選值集合的解析器:

-- parse a rectangular block of characters to a map of
-- coordinate to the character, or Nothing for whitespace
parseRectangle :: Parser (Map (Int, Int) (Maybe Char))

data Class = Letter | Digit | Other

classify :: Char -> Class

parseClassifiedRectangle :: Parser (Map (Int, Int) (Maybe Class))
parseClassifiedRectangle = fmap (fmap (fmap classify)) parseRectangle

圍繞嵌套fmap的一些好方法是什么? 通常它不像這里那么清晰,我最終添加了fmap直到代碼類型檢查。 簡單的代碼最終成為fmap樣板的混亂,我真正想要表達的是“將此函數提升到適當的深度並將其應用於包含的類型”。

一些想法,到目前為止我都沒有發現特別令人滿意的想法:

  • define fmap2 :: (Functor f, Functor g) => (a -> b) -> g (fa) -> g (fb)和朋友
  • 定義具體的助手,比如mapMaybeMap :: (a -> b) -> Map k (Maybe a) -> Map k (Maybe b)
  • 為functor堆棧引入newtype包裝器,並創建Functor那些實例,如newtype MaybeMapParser a = Parser (Map (Int, Int) (Maybe a))

其他人是否在大型代碼庫中遇到此問題? 這甚至是個問題嗎? 你如何解決?

讓我在這個有趣的問題上打破僵局,人們似乎很難回答這個問題。 這個問題可能歸結為風格問題而不是任何問題,因此缺乏答案。

我的方法如下:

parseClassifiedRectangle :: Parser (Map (Int, Int) (Maybe Class))
parseClassifiedRectangle = doClassify <$> parseRectangle
  where
    doClassify = Map.map (fmap classify)

我嘗試使用<$>作為頂級Functor,並為內部fmap函數保存fmap ; 雖然這在實踐中並不總是很好。

我使用了本地命名綁定。 但即使將doClassify保留為f它有時也有助於澄清發生的事情的高級別觀點:“在解析的價值上,我們正在做一件事情,請參閱下面的內容。” 我不知道制作綁定的效率問題是什么。

我還為Map實例使用了fmap的特定實例。 這有助於我在堆棧中定位並為最終的fmap提供路標。

希望這可以幫助。

暫無
暫無

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

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