我从ReaderT
获得了Control.Monad.Reader
:
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
来自Action
的和Database.MongoDB.Query
:
type Action = ReaderT MongoContext
MongoDB的查询功能如下:
delete :: MonadIO m => Selection -> Action m ()
我正在尝试使用Action m ()
模式mathing检查它是Action IO ()
还是Action _ ()
像这样的简单案例
case x of
Action IO () -> True
Action _ () -> False
不起作用,因为Action
不是数据构造函数。可能我应该使用这样的东西:
case x of
ReaderT MongoContext IO () -> True
ReaderT MongoContext _ () -> False
但后来我收到了一个错误:
The constructor ‘ReaderT’ should have 1 argument, but has been given 3
In the pattern: ReaderT MongoContext IO ()
In a case alternative:
ReaderT MongoContext IO ()
我应该通过MongoContext -> IO ()
吗?我没有想法,请帮我说一下。谢谢< 3
答案 0 :(得分:4)
IO是一种类型,你绝对不能大小写匹配它,它只存在于编译时。
通常,如果您有一个受类型类约束的类型变量,则只能调用该类型类支持的内容。除非类型类实现了检查它的方法,否则您无法知道它是哪种特定类型,例如Typeable
。 Monad
和MonadIO
都没有实现这种运行时类型歧视,所以你想要的是设计,不可能。
另请注意,您不需要知道"哪个" delete
是m
,因为它专门针对您希望的MonadIO
,只要它是deleteIO sel = delete sel :: Action IO ()
的实例。您只需声明CREATE OR REPLACE TYPE stringlist IS TABLE OF VARCHAR2(4000);
/
CREATE OR REPLACE TYPE cloblist IS TABLE OF CLOB;
/
CREATE OR REPLACE FUNCTION blob_to_clob (blob_in IN BLOB)
RETURN CLOB
AS
c_buffer CONSTANT PLS_INTEGER := 32767;
v_clob CLOB;
v_varchar VARCHAR2(32767);
v_start PLS_INTEGER := 1;
BEGIN
DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
FOR i IN 1 .. CEIL( DBMS_LOB.GETLENGTH(blob_in) / c_buffer ) LOOP
v_varchar := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, c_buffer, v_start));
DBMS_LOB.WRITEAPPEND(v_clob, LENGTH(v_varchar), v_varchar);
v_start := v_start + c_buffer;
END LOOP;
RETURN v_clob;
END blob_to_clob;
/
SHOW ERRORS;
CREATE OR REPLACE FUNCTION split_clob(
i_str IN CLOB,
i_delim IN VARCHAR2 DEFAULT ','
) RETURN stringlist /* or cloblist */ DETERMINISTIC PIPELINED
AS
p_start PLS_INTEGER := 1;
p_end PLS_INTEGER;
c_len CONSTANT PLS_INTEGER := DBMS_LOB.GETLENGTH( i_str );
c_ld CONSTANT PLS_INTEGER := LENGTH( i_delim );
BEGIN
IF c_len > 0 THEN
p_end := DBMS_LOB.INSTR( i_str, i_delim, p_start );
WHILE p_end > 0 LOOP
PIPE ROW ( DBMS_LOB.SUBSTR( i_str, p_end - p_start, p_start ) );
p_start := p_end + c_ld;
p_end := DBMS_LOB.INSTR( i_str, i_delim, p_start );
END LOOP;
IF p_start <= c_len + 1 THEN
PIPE ROW ( DBMS_LOB.SUBSTR( i_str, c_len - p_start + 1, p_start ) );
END IF;
END IF;
END;
/
你真的想在这里完成什么?
答案 1 :(得分:0)
正如Steven Armstrong所说,你要做的事情非常奇怪,你不能在IO上进行模式匹配,因为是抽象数据类型(构造函数不是&t;如果我是你,我会重新思考我想要达到的目标。话虽如此,Haskell仍然提供了一种使用Typeable在运行时检查类型的方法,例如(在ghci会话中):
import Data.Typeable
import Control.Monad.Trans.Reader
type MyType = ReaderT String IO
f :: MyType ()
f = ReaderT $ \env -> putStrLn env
checkF :: Typeable a => MyType a -> Bool
checkF x = case show (typeOf x) of
"ReaderT * [Char] IO ()" -> True
_ -> False
-- checkF f => True