Tôi vừa tìm thấy Const
trong tài liệu của Control.Applicative
, nhưng tôi gặp khó khăn khi làm việc ở nơi hữu ích này, chỉ sử dụng trực tiếp Monoid
.Trình biên dịch ứng dụng 'Const' hữu ích cho việc gì?
Tôi đang thiếu gì?
Tôi vừa tìm thấy Const
trong tài liệu của Control.Applicative
, nhưng tôi gặp khó khăn khi làm việc ở nơi hữu ích này, chỉ sử dụng trực tiếp Monoid
.Trình biên dịch ứng dụng 'Const' hữu ích cho việc gì?
Tôi đang thiếu gì?
Nó khá hữu ích khi kết hợp với Traversable
.
getConst . traverse Const :: (Monoid a, Traversable f) => f a -> a
Đó là công thức chung để kết hợp nhiều thứ với nhau. Đó là một trong những trường hợp sử dụng đã thuyết phục tôi rằng nó có giá trị tách biệt Applicative
từ Monad
. Tôi cần những thứ như tổng quát elem
elem :: Eq x => x -> Term x -> Bool
làm xảy ra kiểm tra cho một Traversable Term
parametrized bởi các đại diện của các biến miễn phí. Tôi tiếp tục thay đổi sự đại diện của Term
và tôi đã chán ngấy sửa đổi một chức năng truyền tải zillion, một số trong đó đã làm tích lũy, chứ không phải là ánh xạ hiệu quả. Tôi rất vui khi tìm thấy một sự trừu tượng bao phủ cả hai.
Tính năng này hữu ích khi bạn có chức năng hoặc cấu trúc dữ liệu hoạt động cho tất cả (Applicative
) Functor
s và muốn sử dụng lại nó theo nghĩa thoái hóa. Nó tương tự để chuyển qua số const
hoặc id
cho các chức năng hoạt động với các chức năng tùy ý.
Van Laarhoven lenses được xác định theo Functors tùy ý và sử dụng Const
để lấy được một trình truy cập trường (và sốtầm thường để lấy được trình cập nhật trường).
Traversable
các loại, như đề cập của pigworker, là một ví dụ khác về điều này.
Như đã đề cập dave4420, việc triển khai trình truy cập và trình cập nhật cho thấu kính Van Laarhoven liên quan đến Const
functor. Để xây dựng:
{-# LANGUAGE Rank2Types #-}
import Control.Applicative
import Control.Monad.Identity
-- The definition of Van Laarhoven lenses:
type Lens a b = forall f . Functor f => (b -> f b) -> (a -> f a)
-- Getter passes the Const functor to the lens:
get :: Lens a b -> a -> b
get l = getConst . (l Const)
-- Updater passes the Identity functor to the lens:
modify :: Lens a b -> (b -> b) -> (a -> a)
modify l f = runIdentity . l (Identity . f)
set :: Lens a b -> b -> (a -> a)
set l r = modify l (const r)
-- Example: -------------------------------------------
data Person = Person { _name :: String, _age :: Int }
deriving Show
name :: Lens Person String
name f (Person n a) = fmap (\x -> Person x a) (f n)
age :: Lens Person Int
age f (Person n a) = fmap (\x -> Person n x) (f a)
main :: IO()
main = do
let john = Person "John" 34
print $ get age john
print $ set name "Pete" john
Như Gabriel Gonzalez chỉ ra, Const được sử dụng để cung cấp Getters để ống kính. http://hackage.haskell.org/package/lens-tutorial-1.0.0/docs/Control-Lens-Tutorial.html. Ở đó bạn chỉ sử dụng Const đó là một hàm.
Để truyền tải, bạn cần có hành vi áp dụng đầy đủ và nó trở thành những gì pigworker được mô tả trong câu trả lời khác.
http://www.soi.city.ac.uk/~ross/papers/Applicative.html phần 4 là tài liệu tham khảo tốt cho mẹo lừa đảo –
Không có 'foldMap id' tạo kết quả tương tự với ít ràng buộc hơn ('Có thể gập lại' thay vì' Traversable')? –
Thật vậy, đó là lý do tại sao 'Có thể gập lại 'tồn tại. Tuy nhiên, nó khá hữu ích mà tất cả mọi thứ 'Traversable' là' Có thể gập lại', với ở trên là việc xây dựng 'foldMapDefault'. Plug: SHE hỗ trợ 'DefaultSuperclassInstances', để mọi thứ' Traversable' là do mặc định im lặng làm 'Có thể gập lại' theo cách đó. – pigworker