2014-12-18 19 views
6

Giả sử tôi đã có những chức năng sau:Haskell: Có cách nào để suy ra kiểu trả về của hàm từ bên trong hàm không?

import Data.Typeable 
import Text.Read (reads) 

parse :: (Read b, Typeable b) => String -> IO b 
parse msg = case reads msg of 
     [(value,"")] -> return value 
     _ -> throwIO $ ErrorCall ("could not parse " ++ msg) 

Nó phân tích một String vào bất cứ điều gì tôi muốn nó. Nếu chuỗi không đúng định dạng, nó sẽ ném một ngoại lệ hiển thị thông báo, không thể phân tích cú pháp.

tôi sử dụng chức năng này trong một khối việc phải làm của IO-Monad như

(a,b) <- parse msg :: IO (Int,Int) 

và tại một nơi khác như

s <- parse msg :: IO String 

Bây giờ, nếu tôi muốn để làm ngoại trừ báo cáo tiết hơn loại nó không đọc được

import Data.Typeable 
import Text.Read (reads) 

parse :: (Read b, Typeable b) => String -> IO b 
parse msg = case reads msg of 
     [(value,"")] -> return value 
     _ -> throwIO $ ErrorCall ("could not parse " ++ msg ++ " as " ++ 
         show (typeOf something_that_has_type_b)) 

làm cách nào để lấy thứ gì đó có loại b?

Một cách giải quyết có thể sẽ được làm điều này

import Data.Typeable 
import Text.Read (reads) 

parse :: (Read b, Typeable b) => b -> String -> IO b 
parse dummy msg = case reads msg of 
     [(value,"")] -> return value 
     _ -> throwIO $ ErrorCall ("could not parse " ++ msg ++ " as " ++ 
         show (typeOf dummy)) 

và gọi nó như

s <- parse "" msg :: IO String 

Nhưng điều đó có vẻ khá ngớ ngẩn.

Có cách nào để suy ra loại trả về của hàm từ bên trong hàm không?

+0

Ngoài ra: Điều gì xảy ra nếu bạn muốn * trả về * giá trị của một loại cụ thể khi được yêu cầu và lỗi nếu loại trả lại không được yêu cầu? – Evi1M4chine

Trả lời

12

Bạn không cần biến giả, bạn có thể sử dụng tiện ích mở rộng ScopedTypeVariables.

{-# LANGUAGE ScopedTypeVariables #-} 

parse :: forall b. (Read b, Typeable b) => String -> IO b 
parse msg = case reads msg of 
    [(value,"")] -> return value 
    _ -> error $ "could not parse " ++ msg ++ " as " ++ 
        show (typeOf (undefined :: b)) 
+6

Có vẻ như những ngày này tất cả những đứa trẻ tuyệt vời đang sử dụng 'Proxy' thay vì' undefined' cho loại điều này. – dfeuer

+0

@dfeuer Yep, đó là chính xác. Thật xấu hổ khi sử dụng 'undefined' khi' Proxy' nằm trong 'base' ngay bây giờ. –

+3

Vâng, cách hiện đại là 'show (typeRep (Proxy :: Proxy b))'. – augustss

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