2013-04-05 25 views
6

Nói rằng tôi có một chức năng (nó không có bất kỳ ứng dụng thực tế, chỉ cần quan tâm đến học tập, cách như vậy, lạ để viết nó, với monoids, functors applicative và combinators fixpoint)Debugging Sum vô hạn trong Haskell

f :: Num a => a -> Sum a 
f = fix ((<>) <$> Sum <*>) 

Nó gõ, nhưng tôi không thể chắc chắn nó làm những gì nó dự kiến ​​sẽ làm trước khi tôi có thể kiểm tra nó.

Làm cách nào để thử nghiệm và/hoặc gỡ lỗi? Tôi có nghĩa là một cái gì đó giống như nhìn thấy kết quả sau nhiều lần lặp lại như nó có thể với take 10 [1..].

tôi biết một chút về cơ sở vật chất gỡ lỗi đơn giản của ghci như :break:step, nhưng nó bước vào tính không kết thúc vì vậy tôi không thể kiểm tra bất cứ điều gì (nó thậm chí còn có vấn đề để ^C nó). Và tôi cũng không thể tìm cách sử dụng trace từ mô-đun Debug trong chức năng này.

Mọi con trỏ sẽ được đánh giá cao.

+0

Vâng, bạn dễ dàng nhìn thấy những gì nó làm nếu bạn mở rộng nó để 'f = sửa chữa (\ g -> \ x -> Tổng x <> gx)' – phg

Trả lời

10

Gói ChasingBottoms với nó approxShow có thể giúp bạn khám phá các giá trị đánh giá phần:

$ cabal install ChasingBottoms 
$ ghci 
> import Test.ChasingBottoms.ApproxShow 
> import Data.Function 
> approxShow 10 (fix (1:)) 
"[1, 1, 1, 1, 1, 1, 1, 1, 1, _" 

Tuy nhiên, ở đây chúng tôi không thể sử dụng nó trực tiếp: tổng trên Integer s là nghiêm ngặt, không giống như (:) được sử dụng để xây dựng một danh sách. Do đó một loại khác nên được sử dụng.

Thứ nhất, một số hàng nhập khẩu (chúng ta cũng cần để có thể lấy được Data, do đó approxShow có thể được sử dụng để hiển thị kiểu tùy chỉnh của chúng tôi):

{-# LANGUAGE DeriveDataTypeable #-} 

import Data.Data 
import Data.Monoid 
import Data.Function 
import Control.Applicative 
import Test.ChasingBottoms.ApproxShow 

Loại bản thân (rất cơ bản), và Num của nó Ví dụ:

data S = N Integer | S :+ S 
    deriving (Typeable, Data) 

instance Num S where 
    (+) = (:+) 
    fromInteger = N 
    --other operations do not need to be implemented 

Cuối cùng, chức năng:

f :: S -> Sum S 
f = fix ((<>) <$> Sum <*>) 

Và đây là cách chúng ta có thể nhìn thấy những gì f đang làm với, nói rằng, một số phổ biến như 1:

*Main> approxShow 5 (getSum (f 1)) 
"(N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _))))" 

Tất nhiên, nó có thể là thú vị hơn để xem sự tiến hóa:

*Main> Control.Monad.forM_ [0..7] $ \i -> putStrLn $ approxShow i (getSum (f 1)) 
_ 
_ :+ _ 
(N _) :+ (_ :+ _) 
(N 1) :+ ((N _) :+ (_ :+ _)) 
(N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _))) 
(N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _)))) 
(N 1) :+ ((N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _))))) 
(N 1) :+ ((N 1) :+ ((N 1) :+ ((N 1) :+ ((N 1) :+ ((N _) :+ (_ :+ _)))))) 
+1

+1, cảm ơn chia sẻ –

+0

Cảm ơn, tôi dường như không có thể áp dụng nó như là chức năng của tôi mặc dù: 'approxShow 5 (f 1)' kết quả trong 'Không có ví dụ cho (Data.Data.Data (Sum Integer))'. Và làm 'approxShow 10 (getSum (f 1))' cũng không chấm dứt. – dmedvinsky

+0

@dmedvinsky: xin lỗi, xấu của tôi (thành thật mà nói, tôi chưa bao giờ nghe nói về 'Sum' trước đây và nghĩ rằng đó là một số loại tùy chỉnh, vì vậy tôi đã không làm phiền bản thân mình để kiểm tra). Đã cập nhật câu trả lời. – Artyom

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