以下程序类型检查和编译:
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)
?
编辑我
在回应@sabauma评论时,我认为eval
的类型签名必须改变,但我不确定它应该是什么。
编辑II
以下是应该发生的事情的一个例子:
branch = Branch example
app (eval branch, Na)
应该给,
Uni (Uni Na,Uni Na)
这是@sabauma的提议。
答案 0 :(得分: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
我不知道这是否具有所需的行为,但它确实没有 琐碎的解决方案。这使您可以在不更改类型签名的情况下离开。
答案 1 :(得分:3)
我的猜测是重新定义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)
但我不能说这种改变是否对你有意义。您可能应该解释一下如何使用您的类型。
答案 2 :(得分:2)
虽然我不完全确定您的代码的目的,并且这可能不是您所追求的,但是下面的类型检查:
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
对于评估很有用,但现在我几乎肯定不是你想要的。