2013-03-13 4 views
3

Следующая программа типа проверок и составляет:Оценка в AST (как GADT) со стрелками, как атомарные значения

import Control.Arrow 

data Ns = Na | Nb | Nc | Nd deriving Show 

data Net a where 
    Uni :: a -> Net a 
    Serial :: Net a -> Net a -> Net a 
    Branch :: Show a => Net a -> Net (Net a, Net a) 

deriving instance Show a => Show (Net a) 

eval :: (Arrow a) => Net c -> a b (Net c) 
eval (Uni m) = arr (const (Uni m)) 
eval (Serial m n) = eval m >>> eval n 
--eval (Branch m) = eval m &&& eval m 

example = Serial (Serial (Uni Na) (Uni Nb)) (Serial (Uni Nc) (Uni Nd)) 

main = do 
    putStrLn $ show (app (eval example, Na)) 

Однако, когда я пытаюсь добавить случай для eval (Branch m), тип проверки бомбы вне. Что-то типа

Arrow a => a b (Net d) 

ожидается, но, конечно, как у меня есть это

Arrow a => a b (c',c'') 

Кто-нибудь есть предложение о том, как писать eval (Branch m)?

EDIT Я

В ответ на @sabauma замечания, я думаю, тип подписи для eval будет меняться, но я не уверен, что это должно быть.

EDIT II

Вот пример того, что должно произойти:

branch = Branch example 
app (eval branch, Na) 

должен дать,

Uni (Uni Na,Uni Na) 

Это то, что делает @sabauma «s предложение.

+3

Вы уверены, что опубликованные типы кода? Даже когда последний комментарий был прокомментирован, я все еще получаю ошибку типа, связанную с подписью, которую вы положили на 'eval'. GHC указывает тип 'eval :: Arrow a => Net a -> a (Net a) (Net a)'. – sabauma

+0

@sabauma Я исправил объявление типа для 'eval'. По крайней мере, изменили его на то, как я это сделал, прежде чем пытаться добавить 'eval (Branch m)' – lafras

+1

. Вы должны обязательно добавить некоторые примеры с ожидаемыми результатами или дополнительные объяснения по семантике.Очень сложно догадаться, что именно «eval» должен делать точно, учитывая предоставленную вами информацию. – phg

ответ

3

Одной из возможностей является

eval :: (Arrow a) => Net c -> a b (Net c) 
eval (Uni m)  = arr (const (Uni m)) 
eval (Serial m n) = eval m >>> eval n 
eval (Branch m) = (eval m &&& eval m) >>> arr Uni 

Я не знаю, имеет ли это желаемое поведение, но typechecks и не тривиальное решение. Это позволяет вам уйти без изменения сигнатуры типа.

+0

Это выглядит правильно. 'eval (Branch (Uni Na)) дает мне то, что я ожидаю, т. е. Uni (Uni Na, Uni Na). Мне просто нужно немного поразмыслить над семантикой. – lafras

2

Хотя я не совсем уверен, что от цели вашего кода, и это не может быть то, что вы после этого, следующие typechecks:

eval :: Arrow a => Net c -> a b (Net c) 
eval (Uni m)  = arr (const (Uni m)) 
eval (Serial m n) = eval m >>> eval n 
eval (Branch m) = arr (const (Branch m)) 

конечно, arr . const тривиальным работает для Eval, но теперь я почти уверен, что это не то, что вы хотели.

3

Мое предположение было бы redifine Branch принимать два аргумента (так как ветвления как-то предполагает, что для меня):

data Net a where 
    Uni :: a -> Net a 
    Serial :: Net a -> Net a -> Net a 
    Branch :: Show a => Net a -> Net a -> Net (Net a, Net a) 

приводит к

eval :: (Arrow a) => Net c -> a b (Net c) 
eval (Uni m) = arr (const $ Uni m) 
eval (Serial m n) = eval m >>> eval n 
eval (Branch l r) = (eval l) &&& (eval r) >>> arr (uncurry Branch) 

Но я не могу сказать, если это изменение имеет смысл для вас. Вероятно, вам следует объяснить, как будет использоваться ваш тип.

 Смежные вопросы

  • Нет связанных вопросов^_^