2011-09-13 32 views
10

Tôi đang xem qua gói Cloud Haskell Encoding.hs và gặp phải một số mã lạ mà tôi hy vọng ai đó có thể giúp tôi hiểu rõ hơn. Bao gồm là mã cần thiết:mã ma thuật haskell, những gì đang xảy ra ở đây

class (Binary a,Typeable a) => Serializable a 
instance (Binary a,Typeable a) => Serializable a 

data Payload = Payload 
    { 
     payloadType :: !ByteString, 
     payloadContent :: !ByteString 
    } deriving (Typeable) 

serialDecodePure :: (Serializable a) => Payload -> Maybe a 
serialDecodePure a = (\id -> 
    let pc = payloadContent a 
    in pc `seq` 
     if (decode $! payloadType a) == show (typeOf $ id undefined) 
     then Just (id $! decode pc) 
     else Nothing) id 

Tôi chỉ tò mò về những gì $! (Tôi đoán chỉ là đánh giá nghiêm túc), và cũng là lý do tại sao chúng ta cần lừa id (một cái gì đó với đánh giá lười biếng?). Ngoài ra tôi đang đặc biệt gặp vấn đề với dòng này:

if (decode $! payloadType a) == show (typeOf $ id undefined) 

Tôi đoán này được nhìn thấy nếu PayloadType là không hợp lệ vì lý do gì, nhưng nếu đó là trường hợp nên không phải là sau đó và else khoản được bật, tức là thay đổi:

if (decode $! payloadType a) == show (typeOf $ id undefined) 
    then Just (id $! decode pc) 
    else Nothing 

để

if (decode $! payloadType a) == show (typeOf $ id undefined) 
    then Nothing 
    else Just (id $! decode pc) 

Nhờ sự giúp đỡ bạn có thể cung cấp.

+0

Có, 'f $! x' là ứng dụng nghiêm ngặt. Bạn có thể tìm thấy [bài viết này] (http://neilmitchell.blogspot.com/2008/05/bad-strictness.html) khai sáng về cách thêm tính nghiêm ngặt hoạt động. –

+0

Xem thêm http://stackoverflow.com/q/2787543/246886 –

Trả lời

12

Bạn đúng là $! là bộ đánh giá nghiêm ngặt. Kiểu của nó giống hệt với $ và khác biệt ngữ nghĩa duy nhất là đối số thứ hai là seq 'd trước khi được chuyển đến hàm.

Tôi nghĩ rằng id thực sự ở đó để giúp suy luận kiểu. Trong khối chức năng (\id -> ...), hàm id buộc phải có loại a -> a, nơi a không chỉ là bất kỳ loại biến, nhưng cùng a như trong

serialDecodePure :: (Serializable a) => Payload -> Maybe a 

Điều này là do dòng này:

Just (id $! decode pc) 

vì loại này có loại Maybe a, id có loại được phỏng đoán a -> a.Do đó, trên dòng bạn đang nhìn vào,

if (decode $! payloadType a) == show (typeOf $ id undefined) 

id undefined :: a, nơi a là một lần nữa giống như đầu ra.

Bây giờ, chúng tôi có thể kiểm tra loại. Vì chức năng này đa hình và sẽ giải mã thành bất kỳ loại nào, cần kiểm tra xem dữ liệu được mã hóa có tương thích với loại mà nó giải mã hay không. Điều gì sẽ xảy ra nếu bạn mã hóa một số String và đang cố gắng giải mã thành một số Int? LHS sẽ giải mã thành "[Char]", là biểu diễn TypeRep của một String. RHS thay vào đó sẽ là "Int", loại nó đang cố gắng giải mã. Vì chúng không bằng nhau, đường dẫn "khác" là đường dẫn trả về None.

Thay vì hạn chế loại chức năng id này, bạn có thể thực hiện điều tương tự với tiện ích mở rộng ScopedTypeVariables.

+1

ồ người đàn ông mà điều id là cách thông minh –

4

Ồ, đó là một số mã lạ! Như bạn có thể đoán, ($!) là về tính nghiêm minh:

f $! x = x `seq` f x 

Các id Bí quyết là sneakier, và là tất cả về loại hạn chế. Bạn sẽ nhận thấy rằng id được sử dụng hai lần trong phần thân hàm. Lần thứ hai nó được sử dụng như id $! decode pc; điều này sửa lỗi loại id để hoạt động trên bất kỳ loại kết quả đầu ra nào decode. Việc sử dụng đầu tiên là typeOf $! id undefined; vì loại id đã được sửa, nên sửa lỗi kiểu undefined, sao cho typeOf được áp dụng cho đối số đơn lẻ (và bạn không nhận được lỗi "loại mơ hồ"). Loại điều này thường được thực hiện với tiện ích mở rộng ScopedTypeVariables thay vì mẹo này, nhưng có lẽ họ muốn tránh các tiện ích mở rộng bất cứ khi nào có thể. Đối với các ý nghĩa của điều này:

(decode $! payloadType a) == show (typeOf $ id undefined) 

... có vẻ với tôi như vậy được kiểm tra rằng tải trọng phù hợp với loại điều được trả về bởi các cuộc gọi đến decode tại các chi nhánh then. Có vẻ như có ý nghĩa khi có giá trị Just (tức là thành công) khi chúng khớp nhau và giá trị Nothing (nghĩa là không thành công) khi chúng không khớp.

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