Tôi muốn sử dụng số lens library của Kmett để truy cập vào phần tử của danh sách (khóa, giá trị) theo một khóa cụ thể. Nói cách khác, tôi muốn thay thế mã này với một cái gì đó nhiều thành ngữ và có lẽ ngắn hơn:Sử dụng ống kính để thay thế một phần tử cụ thể của danh sách (khóa, giá trị)
type Headers = [ (ByteString, ByteString) ]
headerLens ::
Functor f =>
ByteString ->
(Maybe ByteString -> f (Maybe ByteString)) ->
Headers ->
f Headers
headerLens header_name f headers
| old_header_value <- fetchHeader headers header_name = fmap
(\ new_header_value ->
replaceHeaderValue
headers
header_name
new_header_value
)
(f old_header_value)
nơi các chức năng hỗ trợ được quy định như sau:
-- | Looks for a given header and returns the value, if any
fetchHeader :: Headers -> ByteString -> Maybe ByteString
fetchHeader headers header_name =
snd <$> find (\ x -> fst x == header_name) headers
-- | replaceHeaderValue headers header_name maybe_header_value looks for
-- header_name. If header_name is found and maybe_header_value is nothing, it
-- returns a new headers list with the header deleted. If header_name is found
-- and header_value is Just new_value, it returns a new list with the header
-- containing the new value. If header_name is not in headers and maybe_header_value
-- is Nothing, it returns the original headers list. If header_name is not in headers
-- and maybe_header_value is Just new_value, it returns a new list where the last element
-- is (header_name, new_value)
replaceHeaderValue :: Headers -> ByteString -> Maybe ByteString -> Headers
replaceHeaderValue headers header_name maybe_header_value =
disect id headers
where
disect builder [] = case maybe_header_value of
Nothing -> headers
Just new_value -> builder $ (header_name, new_value):[]
disect builder ([email protected](hn,hv) : rest)
| hn /= header_name =
disect
(\ constructed_list -> builder $ el:constructed_list)
rest
| otherwise = case maybe_header_value of
Nothing -> builder rest
Just new_value -> builder $ (hn, new_value):rest
Cảm ơn @bheklilr. Bạn đang đúng về việc đặt hàng là quan trọng, và nói chung tôi đã kiềm chế từ tối ưu hóa trước khi hồ sơ. – dsign
@dsign Nếu trường hợp đó xảy ra, bạn chỉ cần sử dụng loại 'Tiêu đề', thay thế' M.lookup' bằng 'Prelude.lookup' và triển khai lại [' Data.Map.alter'] (http: //hackage.haskell. org/package/containers-0.5.6.3/docs/src/Data-Map-Base.html # alter) cho các danh sách liên kết, đây sẽ là một mẹo nhỏ. Hoặc bạn có thể duyệt xung quanh Hackage một lúc để tìm xem liệu có ai khác đã làm điều đó chưa, bởi vì họ có thể có. – bheklilr
Điểm tốt. Một chi tiết nhỏ khó chịu mà tôi vừa mới nhận ra là tôi không thể tuân thủ luật ống kính trong thiết lập hiện tại .... vì vậy tôi nghĩ tôi cần chuyển sang bản đồ và đặt các khóa bằng chức năng tùy chỉnh (không phải là từ điển, nhưng có một thứ tự * thích hợp *). Cảm ơn! – dsign