2011-12-26 25 views
5

Tôi vừa mới bắt gặp "loại vô hạn" trong Haskell khi tôi đang cố viết một máy trạng thái hữu hạn. Tôi nghĩ những điều sau đây là rất trực quan:Các loại vô hạn Haskell và chức năng FSM của tôi

fsm []  _  acc = Right acc 
fsm (x:xs) state acc = 
    case state acc x of 
     Left err  -> Left err 
     Right (s, a) -> fsm xs s a 

tôi cung cấp cho các chức năng nhà nước hiện trạng (accumulator) và sự kiện mới, và các chức năng nhà nước tạo ra các chức năng nhà nước tiếp theo cùng với accumulator mới. Tôi chấp nhận cho đến khi tôi không còn sự kiện nữa.

Trình biên dịch nói với tôi:

Occurs check: cannot construct the infinite type: 
    t1 = b0 -> t0 -> Either a0 (t1, b0) 
In the second argument of `fsm', namely `s' 

state hiện nay là một loại vô hạn. Làm thế nào để tôi sắp xếp lại điều này để làm cho nó hoạt động?

Trả lời

8

Các loại vô hạn như thế này sẽ tàn phá với hệ thống kiểu; họ không làm cho nó không an toàn, nhưng chúng gây ra rất nhiều chương trình để gõ mà bạn không thực sự muốn, do đó ẩn lỗi, và tôi tin rằng họ làm cho suy luận kiểu khó hơn.

Rất may, giải pháp rất đơn giản: bạn chỉ cần tạo một bao bì newtype. Tất cả các khai báo datanewtype đều được phép đệ quy (nếu không, chúng tôi thậm chí không thể xác định danh sách!); nó chỉ đơn giản, chưa được loại mà không phải.

newtype FSMState err acc ev = 
    FSMState { stepFSM :: acc -> ev -> Either err (FSMState err acc ev, acc) } 

fsm :: [ev] -> FSMState err acc ev -> acc -> Either err acc 
fsm []  _  acc = Right acc 
fsm (x:xs) state acc = 
    case stepFSM state acc x of 
     Left err  -> Left err 
     Right (s, a) -> fsm xs s a 
+0

Cảm ơn. Đối với tôi, tất cả những điều này làm là đặt tên cho loại vô hạn, nhưng chính loại đó vẫn là tự tham chiếu. Trình biên dịch tự nó thậm chí còn đặt tên kiểu vô hạn theo cùng một cách. Tôi đã nghĩ rằng trình biên dịch sẽ có thể tự động hóa điều này bằng cách đặt tên cho nó. Tôi có nhầm không? – Ana

+5

@Ana: Mặc dù Haskell chỉ cho rằng chương trình của bạn không hợp lệ bởi * lựa chọn * và không cần thiết, nó là vì một lý do rất tốt; Tôi không có bất kỳ liên kết nào ngay bây giờ, nhưng * nhiều * lỗi phổ biến mà chúng tôi dựa vào hệ thống kiểu để kiểm tra - như thiếu đối số hoặc viết tên hàm hai lần - trở thành chương trình được nhập hợp lệ (nhưng bị hỏng) nếu bạn cho phép vô hạn loại. – ehird

+3

Lưu ý rằng nó không phải là khá đơn giản như đưa ra một loại tên: 'loại Infinite = (Bool, Infinite)' cũng bị cấm; bạn phải bọc nó trong một * kiểu dữ liệu *, điều này ngăn cản tất cả các khả năng xảy ra lỗi, bởi vì bạn phải xây dựng một cách rõ ràng và khớp mẫu (hoặc sử dụng các hàm truy cập) trên đó. – ehird

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