[英]Does Haskell have pointers/references to record members?
我可以使用::*
, .*
和->*
語法創建和引用C ++中結構成員的相對指針,如:
char* fstab_t::*field = &fstab_t::fs_vfstype;
my_fstab.*field = ...
在Haskell中,我可以輕松地為記錄getter創建臨時標簽,例如:
(idxF_s,idxL_s) = swap_by_sign sgn (idxF,idxL) ;
Afaik,然后我不能使用這些getter更新記錄,如:
a { idxF_s = idxL_s b }
是否有一種簡單的方法可以在不編碼每個記錄設置器的情況下執行此操作
將第一類值捆綁在一起的吸氣劑和定位器稱為透鏡 。 這樣做有很多套餐; 最受歡迎的是數據鏡頭和fclabels 。 以前的SO問題是一個很好的介紹。
這兩個庫都支持使用Template Haskell從記錄定義中導出鏡頭(使用數據鏡頭,它作為可移植性的附加包提供)。 您的示例將表示為(使用數據鏡頭語法):
setL idxF_s (b ^. idL_s) a
(或等效地: idxF_s ^= (b ^. idL_s) $ a
)
當然,你可以通過將他們的getter和setter轉換為一般來改變鏡頭:
-- I don't know what swap_by_sign is supposed to do.
negateLens :: (Num b) => Lens a b -> Lens a b
negateLens l = lens get set
where
get = negate . getL l
set = setL l . negate
(或等效地: negateLens l = iso negate negate . l
1 )
一般來說,我建議您在處理任何類型的非平凡記錄處理時使用鏡頭; 它們不僅極大地簡化了記錄的純轉換,而且兩個包都包含使用鏡頭訪問和修改狀態monad狀態的便利功能,這非常有用。 (對於數據鏡頭,您需要使用data-lens-fd軟件包在任何MonadState
使用這些便捷功能;同樣,它們在一個單獨的軟件包中以便於移植。)
1使用任一軟件包時,您應該使用以下命令啟動模塊:
import Prelude hiding (id, (.))
import Control.Category
這是因為它們使用Prelude的id
和(.)
函數的通用形式 - id
可以用作從任何值到自身的鏡頭(不是所有有用的,不可否認),並且(.)
用於構成鏡頭(例如getL (fieldA . fieldB) a
與getL fieldA . getL fieldB $ a
相同getL fieldA . getL fieldB $ a
)。 較短的negateLens
定義使用它。
你想要的是一流的唱片公司標簽,雖然這種語言不存在,但Hackage上有幾個實現這種模式的軟件包。 其中一個是fclabels ,它可以使用Template Haskell為您生成所需的樣板。 這是一個例子:
{-# LANGUAGE TemplateHaskell #-}
import Control.Category
import Data.Label
import Prelude hiding ((.))
data Foo = Foo { _fieldA :: Int, _fieldB :: Int }
deriving (Show)
$(mkLabels [''Foo])
main = do
let foo = Foo 2 3
putStrLn "Pick a field, A or B"
line <- getLine
let field = (if line == "A" then fieldA else fieldB)
print $ modify field (*10) foo
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.