2017-07-21 16 views
6

Tôi có một kiểu dữ liệu như thế này:Làm thế nào tôi có thể sử dụng Generics để trích xuất tất cả các giá trị của một loại cụ thể?

data MyType = Foo Bool 
      | Bar 
      | Baz Bool (Maybe String) Bool 
      | Quux Int String 

Tôi có thể sử dụng Generics để viết một hàm getBools :: MyType -> [Bool] mà trả về một danh sách tất cả các lĩnh vực boolean trong đầu vào?

tôi đã đưa ra loại chữ ký này:

getAllOfType :: 
    (Generic inner, Generic outer, HasDatatypeInfo inner, All2 HasDatatypeInfo (Code outer)) => 
    Proxy inner -> outer -> [inner] 

Sử dụng generics-sop, nhưng tôi không nghĩ điều đó đúng. So sánh DatatypeInfo s sẽ không thuyết phục trình kiểm tra loại mà hai loại là tương đương nhau.

+3

Nếu bạn sở hữu 'MyType' sau đó bạn có thể viết' MyType' a = Foo a | ... ', thay thế' Bool' bằng 'a' ở mọi nơi và' gõ MyType = MyType 'Bool'. Sau đó, bạn có thể lấy được 'Foldable' (với phần mở rộng' DeriveFoldable') và 'toList' sẽ cung cấp cho bạn một danh sách tất cả các' Bool 'trong cấu trúc của bạn. Không có generics yêu cầu. –

+0

Điều đó thật thú vị, nhưng không thực sự hiệu quả với tôi. Trong thực tế, tôi muốn trích xuất các trường khác nhau tùy thuộc vào trường hợp sử dụng. –

Trả lời

6

Sử dụng uniplate:

{-# LANGUAGE DeriveDataTypeable #-} 

module M where 

import Data.Data 
import Data.Generics.Uniplate.Data 

data MyType 
    = Foo Bool 
    | Bar 
    | Baz Bool (Maybe String) Bool 
    | Quux Int String 
    deriving Data 

getBools :: MyType -> [Bool] 
getBools = universeBi 
Các vấn đề liên quan