2011-05-07 39 views
11

Tôi muốn viết một hàm với kiểu chữ ký này:Haskell - nhận TypeRep từ bê tông loại dụ

getTypeRep :: Typeable a => t a -> TypeRep 

nơi TypeRep sẽ là đại diện cho loại một, không phải cho t một. Tức là, trình biên dịch sẽ tự động trả về biểu diễn kiểu chính xác tại bất kỳ trang web cuộc gọi nào [tới getTypeRep], sẽ có loại bê tông cho a.

Để thêm một số ngữ cảnh, tôi muốn tạo loại dữ liệu "Loại động", với thao tác xoay vòng sẽ ghi nhớ loại cấp cao nhất, chứ không phải thông số của nó. Ví dụ, tôi muốn chuyển MyClass một vào động MyClass, và các chức năng trên sẽ được sử dụng để tạo ra các trường hợp động MyClass lưu trữ một đại diện của các tham số kiểu một.

Trả lời

9

Vâng, làm thế nào về việc sử dụng các biến kiểu chỉnh phạm vi để chọn các thành phần bên trong:

{-# LANGUAGE ExplicitForAll #-} 
{-# LANGUAGE ScopedTypeVariables #-} 

import Data.Dynamic 
import Data.Typeable 

getTypeRep :: forall t a . Typeable a => t a -> TypeRep 
getTypeRep _ = typeOf (undefined :: a) 

trình cho tôi:

*Main> getTypeRep (Just()) 
() 
*Main> getTypeRep (Just 7) 
Integer 
*Main> getTypeRep ([True]) 
Bool 

Thú vị thiết kế.

8

Lưu ý tiếp theo cho giải pháp của Don, hãy chú ý rằng mã hiếm khi yêu cầu ScopedTypeVariables. Nó chỉ làm cho giải pháp sạch hơn (nhưng ít cầm tay hơn). Các giải pháp mà không loại scoped là:

{-# LANGUAGE ExplicitForAll #-} 
import Data.Typeable 

helper :: t a -> a 
helper _ = undefined 

getTypeRep :: forall t a. Typeable a => t a -> TypeRep 
getTypeRep = typeOf . helper 
1

Chức năng này (bây giờ) tồn tại trong Data.TypeabletypeRep

Các vấn đề liên quan