2011-06-27 25 views
7

Tôi đang sử dụng thư viện Hoopl và muốn thực hiện một số trạng thái xung quanh khi viết lại. Các hàm viết lại có tính đa hình liên quan đến đơn nguyên được sử dụng, nhưng tôi không thể tìm ra cách kết hợp một đơn nguyên State với một trong các monome Fuel của thư viện.Làm cách nào để kết hợp CheckingFuelMonad với một đơn vị Tiểu bang trong Hoopl?

Dưới đây là ví dụ tối thiểu. MyMonad là một từ đồng nghĩa kết hợp số CheckingFuelMonad của Hoopl và một đơn vị State mang cờ. Stmt chỉ là một trình giữ chỗ cho ngôn ngữ trung gian của tôi và không thực sự quan trọng.

{-# LANGUAGE GADTs, RankNTypes #-} 

import Compiler.Hoopl 
import Control.Monad.State 

type MyMonad = CheckingFuelMonad (State Bool) 

data Stmt e x where 
    Bind ::() -> Stmt O O 

rewriter :: forall e x. Stmt e x -> Fact x() -> MyMonad (Maybe (Graph Stmt e x)) 
rewriter (Bind())() = return $ do 
    f <- get 
    if f 
    then return $ Just emptyGraph 
    else return Nothing 

Nhưng điều này sẽ không biên dịch - GHC phàn nàn rằng rewrite có kiểu sai:

Couldn't match expected type `Graph' Block Stmt e x' 
     against inferred type `Maybe (g n O O)' 
    Expected type: CheckingFuelMonad 
        (State Bool) (Maybe (Graph Stmt e x)) 
    Inferred type: CheckingFuelMonad 
        (State Bool) (Maybe (Maybe (g n O O))) 

phải là những gì tôi muốn làm tốt? Làm cách nào để tôi có thể viết chính xác chức năng rewrite?

+0

Tôi cực kỳ không tin rằng việc viết lại này là âm thanh. Đây là hoạt động kinh doanh rất tinh ranh. –

Trả lời

4

Duyệt qua mã hoopl tiết lộ rằng CheckingFuelMonad không phải là một phiên bản của MonadTrans, và bạn không thể làm cho nó một, vì các hàm tạo của nó không được xuất. Bạn có thể tuy nhiên quấn một StateT xung quanh CheckingFuelMonad, như vậy:

{-# LANGUAGE GADTs, RankNTypes #-} 

import Compiler.Hoopl 
import Control.Monad.State 

type MyMonad = StateT Bool SimpleFuelMonad 

data Stmt e x where 
    Bind ::() -> Stmt O O 

rewriter :: forall e x. Stmt e x -> Fact x() -> MyMonad (Maybe (Graph Stmt e x)) 
rewriter (Bind())() = do 
    f <- get 
    if f 
    then return $ Just emptyGraph 
    else return Nothing 
+0

Phần buồn cười là, nếu bạn nhìn vào việc thực hiện 'CheckingFuelMonad', nó chỉ là' StateT Fuel'. –

+0

Điều đó giúp tôi tiến xa hơn một chút! Thật không may 'MyMonad' phải là một thể hiện của' FuelMonad', và tôi không nghĩ rằng tôi có thể làm cho nó một kể từ khi các thành viên lớp học không được xuất khẩu. Tuy nhiên, tôi có thể lấy đi với 'mkBRewrite (\ s f -> evalStateT (viết lại s f) Sai)'. Thật không may, tôi nghĩ rằng điều đó có nghĩa là tiểu bang sẽ không được bảo tồn qua các phát biểu cá nhân - chúng ta sẽ thấy! –

+0

@Justin Bailey: Mọi thứ từ 'FuelMonad' trông giống như nó được xuất khẩu cho tôi. Ngoài ra, tôi khá chắc chắn rằng thứ tự không liên quan đến các lớp * lân cận * 'StateT', vì vậy phiên bản' sclv' phải tương đương với việc đặt 'State' bên trong' SimpleFuelMonad'. –

1

Vâng, nguyên nhân trực tiếp của lỗi hiện tại của bạn là đơn giản. Biểu thức cuối cùng là gì nếu f là đúng? Nếu chúng ta thực hiện việc này:

rewriter :: forall e x. Stmt e x -> Fact x() -> MyMonad (Maybe (Graph Stmt e x)) 
rewriter (Bind())() = return $ do 
    f <- get 
    if f 
    then return $ Just emptyGraph 
    else return Nothing 

... và loại bỏ tất cả mọi thứ nhưng chi nhánh True chúng tôi nhận được:

rewriter :: forall e x. Stmt e x -> Fact x() -> MyMonad (Maybe (Graph Stmt e x)) 
rewriter (Bind())() = return $ do 
    return $ Just emptyGraph 

... mà đơn giản hoá để:

rewriter :: forall e x. Stmt e x -> Fact x() -> MyMonad (Maybe (Graph Stmt e x)) 
rewriter (Bind())() = return $ return $ Just emptyGraph 

loại là gì return $ return $ Just emptyGraph?

(Monad m1, Monad m2, GraphRep g) => m1 (m2 (Maybe (g n O O))) 

Nói cách khác, bạn có thêm return trong đó. (Monad m) => CheckingFuelMonad m là chính nó là Monad, mặc dù CheckingFuelMonad dường như không được định nghĩa là một biến áp đơn lẻ, do đó bạn chỉ có một lớp đơn lẻ là return với.

+0

Tước trả lại kết quả trong một lỗi loại khác ... :( –

+0

@Justin Bailey: Do đó tại sao tôi lại nói "nguyên nhân ngay lập tức". Xóa 'return' bên ngoài khối' do' chỉ làm giảm nó thành vấn đề thực tế, đó là những gì 'sclv' nói về. –

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