2012-07-17 25 views

Trả lời

27

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.

+0

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 –

+0

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')? –

+1

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

6

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.

7

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 
Các vấn đề liên quan