Haskell:与命名字段匹配的模式

时间:2017-05-28 19:43:58

标签: haskell pattern-matching monads monad-transformers

我从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

2 个答案:

答案 0 :(得分:4)

IO是一种类型,你绝对不能大小写匹配它,它只存在于编译时。

通常,如果您有一个受类型类约束的类型变量,则只能调用该类型类支持的内容。除非类型类实现了检查它的方法,否则您无法知道它是哪种特定类型,例如TypeableMonadMonadIO都没有实现这种运行时类型歧视,所以你想要的是设计,不可能。

另请注意,您不需要知道&#34;哪个&#34; deletem,因为它专门针对您希望的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