我正在尝试实现一个由点类型索引的“DrawEnv”类型类:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
class Monad m => DrawEnv p m where
box :: p -> p -> m ()
clear :: m ()
line :: p -> p -> m ()
type Pos = (Float,Float)
instance DrawEnv Pos IO where
box p0 p1 = putStrLn $ "Box " ++ show p0 ++ " " ++ show p1
clear = putStrLn "Clear"
line p0 p1 = putStrLn $ "Line " ++ show p0 ++ " " ++ show p1
draw :: DrawEnv Pos m => m ()
draw = do
clear
box (10.0,10.0) (100.0,100.0)
line (10.0,10.0) (100.0,50.0)
然而GHC并不高兴:
Could not deduce (DrawEnv (t0, t1) m) arising from a use of `box'
from the context (DrawEnv Pos m)
bound by the type signature for draw :: DrawEnv Pos m => m ()
at Code/Interfaces3.hs:63:9-29
The type variables `t0', `t1' are ambiguous
Relevant bindings include
draw :: m () (bound at Code/Interfaces3.hs:64:1)
Note: there is a potential instance available:
instance DrawEnv Pos IO -- Defined at Code/Interfaces3.hs:56:10
In a stmt of a 'do' block: box (10.0, 10.0) (100.0, 100.0)
In the expression:
do { clear;
box (10.0, 10.0) (100.0, 100.0);
line (10.0, 10.0) (100.0, 50.0) }
In an equation for `draw':
draw
= do { clear;
box (10.0, 10.0) (100.0, 100.0);
line (10.0, 10.0) (100.0, 50.0) }
我的问题是为什么GHC在Pos约束下不接受这个?
答案 0 :(得分:2)
代码含糊不清。具体来说,我们不知道
的类型。例如,它可能是sub sendMail {
my $params = shift;
my $body;
my $smtp;
( $smtp = Net::SMTP::SSL->new(
'smtp.gmail.com',
Port=>465,
Debug => 1,
Timeout => 60,
Hello => 'smtp2.dnikolov.co.nf@gmail.com',
Notify =>['SUCCESS','FAILURE'],
Debug => 1
) )or die "Cant connect to server".$@.$!;
$smtp->auth('smtp2.dnikolov.co.nf@gmail.com', $params->{password} ) or die "Can't authenticate ".$smtp->message();
return 0 unless $smtp->verify( $params->{readerEmail}->{value} );
$smtp->mail('smtp.dnikolov.co.nf@gmail.com'."\n") or die "Cant from";
$smtp->to('dnikolov.co.nf@gmail.com'."\n") or die "invalid address";
$smtp->data() or die "cant call data successfuly";
$smtp->datasend('From:< "'.$params->{readerEmail}->{value}.'" smtp.dnikolov.co.nf@gmail.com>'."\n");
$smtp->datasend('To:dnikolov.co.nf@gmail.com'."\n");
$smtp->datasend('Subject:'.$params->{readerSubject}->{value}."\n");
$smtp->datasend("\n");
$smtp->datasend('Reader Email: '.$params->{readerEmail}->{value}."\n");
$smtp->datasend('Reader Site: '.$params->{readerSite}->{value}."\n");
$smtp->datasend('Reader Subject: '.$params->{readerSubject}->{value}."\n");
$smtp->datasend('Reader Message: '.$params->{readerMessage}->{value}."\n");
$smtp->dataend()or die "Failed to Send Message";
$smtp->quit() or die "Failed on quit";
return 1;
}
sub sendMail {
my $params = shift;
my $body;
my $smtp;
( $smtp = Net::SMTP::SSL->new(
'smtp.gmail.com',
Port=>465,
Debug => 1,
Timeout => 60,
Hello => 'smtp2.dnikolov.co.nf@gmail.com',
Notify =>['SUCCESS','FAILURE'],
Debug => 1
) )or die "Cant connect to server".$@.$!;
$smtp->auth('smtp2.dnikolov.co.nf@gmail.com', $params->{password} ) or die "Can't authenticate ".$smtp->message();
return 0 unless $smtp->verify( $params->{readerEmail}->{value} );
$smtp->mail('smtp.dnikolov.co.nf@gmail.com'."\n") or die "Cant from";
$smtp->to('dnikolov.co.nf@gmail.com'."\n") or die "invalid address";
$smtp->data() or die "cant call data successfuly";
$smtp->datasend('From:< "'.$params->{readerEmail}->{value}.'" smtp.dnikolov.co.nf@gmail.com>'."\n");
$smtp->datasend('To:dnikolov.co.nf@gmail.com'."\n");
$smtp->datasend('Subject:'.$params->{readerSubject}->{value}."\n");
$smtp->datasend("\n");
$smtp->datasend('Reader Email: '.$params->{readerEmail}->{value}."\n");
$smtp->datasend('Reader Site: '.$params->{readerSite}->{value}."\n");
$smtp->datasend('Reader Subject: '.$params->{readerSubject}->{value}."\n");
$smtp->datasend('Reader Message: '.$params->{readerMessage}->{value}."\n");
$smtp->dataend()or die "Failed to Send Message";
$smtp->quit() or die "Failed on quit";
return 1;
}
。它最常见的类型是(10.0,10.0)
。
解决方法是写
(Double,Double)
而是类似地修复其他行。
答案 1 :(得分:2)
此类定义不起作用,因为clear
的类型没有提及类型变量p
,因此无法使用clear
实例化box
具体类型。将类型签名添加到line
或clear :: IO ()
不会有帮助 - 即使class Monad m => DrawEnv p m | m -> p where
也会产生类型错误。
这可以通过向您的类添加函数依赖项来解决:
class Monad m => MonadDraw m where
putStringLn :: String -> m ()
clear :: m ()
clear = putStringLn "Clear"
class DrawEnv p where
box :: MonadDraw m => p -> p -> m ()
line :: MonadDraw m => p -> p -> m ()
instance (Fractional a, Show a, Fractional b, Show b) => DrawEnv (a,b) where
box p0 p1 = putStringLn $ "Box " ++ show p0 ++ " " ++ show p1
line p0 p1 = putStringLn $ "Line " ++ show p0 ++ " " ++ show p1
draw :: MonadDraw m => m ()
draw = do
clear
box (10.0,10.0) (100.0,100.0)
line (10.0,10.0) (100.0,50.0)
然后你的其余代码编译。或者,您可以将您的班级分为两类:
<mvcSiteMapNode id="Home" title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="Page2" controller="Page2" action="Index"/>
<mvcSiteMapNode title="Page3" controller="Page3" action="Index" />
<mvcSiteMapNode title="Page4" controller="Pag4" action="Index" />
</mvcSiteMapNode>