现有
记录中的字段,并使用形状相似的传入
记录中的字段。以下是我目前的代码:applyUpdater fields existing incoming =
let getters = DL.map (^.) fields
setters = DL.map set fields
updaters = DL.zipWith (,) getters setters
in DL.foldl' (\updated (getter, setter) -> setter (getter incoming) updated) existing updaters
我希望以以下方式使用它:
applyUpdater
[email, notificationEnabled] -- the fields to be copied from incoming => existing (this obviously assumed that `name` and `email` lenses have already been setup
User{name="saurabh", email="blah@blah.com", notificationEnabled=True}
User{name="saurabh", email="foo@bar.com", notificationEnabled=False}
这个不起作用,可能是因为Haskell为applyUpdater
推断出了一个非常奇怪的类型签名,这意味着它没有做我期望的事情:
applyUpdater :: [ASetter t1 t1 a t] -> t1 -> Getting t (ASetter t1 t1 a t) t -> t1
以下是代码示例和编译错误:
module TryUpdater where
import Control.Lens
import GHC.Generics
import Data.List as DL
data User = User {_name::String, _email::String, _notificationEnabled::Bool} deriving (Eq, Show, Generic)
makeLensesWith classUnderscoreNoPrefixFields ''User
-- applyUpdater :: [ASetter t1 t1 a t] -> t1 -> Getting t (ASetter t1 t1 a t) t -> t1
applyUpdater fields existing incoming =
let getters = DL.map (^.) fields
setters = DL.map set fields
updaters = DL.zipWith (,) getters setters
in DL.foldl' (\updated (getter, setter) -> setter (getter incoming) updated) existing updaters
testUpdater :: User -> User -> User
testUpdater existingUser incomingUser = applyUpdater [email, notificationEnabled] existingUser incomingUser
编译错误:
18 62 error error:
• Couldn't match type ‘Bool’ with ‘[Char]’
arising from a functional dependency between:
constraint ‘HasNotificationEnabled User String’
arising from a use of ‘notificationEnabled’
instance ‘HasNotificationEnabled User Bool’
at /Users/saurabhnanda/projects/vl-haskell/.stack-work/intero/intero54587Sfx.hs:8:1-51
• In the expression: notificationEnabled
In the first argument of ‘applyUpdater’, namely
‘[email, notificationEnabled]’
In the expression:
applyUpdater [email, notificationEnabled] existingUser incomingUser (intero)
18 96 error error:
• Couldn't match type ‘User’
with ‘(String -> Const String String)
-> ASetter User User String String
-> Const String (ASetter User User String String)’
Expected type: Getting
String (ASetter User User String String) String
Actual type: User
• In the third argument of ‘applyUpdater’, namely ‘incomingUser’
In the expression:
applyUpdater [email, notificationEnabled] existingUser incomingUser
In an equation for ‘testUpdater’:
testUpdater existingUser incomingUser
= applyUpdater
[email, notificationEnabled] existingUser incomingUser (intero)
^.
和^#
,但是顺序错了。使用DL.map (flip (^#)) fields
能否解决这个问题? - leftaroundaboutapplyUpdater2
、applyUpdater3
、applyUpdater4
等等? - Saurabh NandaapplyUpdater2 (f1, f2) existing incoming = (storing f2 (incoming ^# f2)) $ (storing f1 (incoming ^# f1) existing)
- Saurabh Nanda