首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从(名称、处理程序)对列表中提取名称

从(名称、处理程序)对列表中提取名称
EN

Stack Overflow用户
提问于 2014-12-08 00:47:17
回答 1查看 50关注 0票数 1

下面是一个使用haskeline和StateT转换器创建有状态输入命令循环的简单示例:

代码语言:javascript
复制
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}

import Control.Monad.State.Strict
import Control.Monad.Trans (lift)
import System.Console.Haskeline

main =  runStateT (runInputT defaultSettings loop) ""

check ma b fb = maybe b fb ma

commands :: (MonadState String m, MonadIO m) => [(String, [String] -> InputT m ())]
commands = [ ("set", performSet), ("get", performGet) ]

performSet args = lift $ put (head args)
performGet _ = do v <- lift get; outputStrLn $ "v = " ++ show v

loop :: (MonadException m, MonadState String m) => InputT m ()
loop = do
   minput <- getInputLine "% "
   check minput (return ()) $ \inp -> do
     let args = words inp
     case args of
       [] -> loop
       (arg0:argv) -> do
         case lookup arg0 commands of
           Nothing      -> do outputStrLn "huh?"; loop
           Just handler -> do handler argv; loop

列表commands包含所有可识别的命令-对(名称、处理程序)。我希望使用如下表达式获取名称列表:

代码语言:javascript
复制
commandNames = map fst commands

但是类型检查器抱怨“(MonadState String m0)由于使用‘m0’-类型变量‘m0’是不明确的.”

我需要做什么来满足类型检查?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-12-08 01:28:52

commands是多态的,它有一个类型变量m,但是commandNames :: [String]没有任何类型变量。这意味着(除非有一些内置的默认值)类型推断将无法推断commands的类型变量。你可以做两件事。您可以自己为commands提供一个类型

代码语言:javascript
复制
commandNames :: [String]
commandNames = map fst (commands :: [(String, [String] -> InputT (StateT String IO) ())])

或者,您可以更改代码,以便根据较少的变量定义具有更多类型变量的值。

代码语言:javascript
复制
commandNames :: [String]
commandNames = ["set", "get"]

commands :: (MonadState String m, MonadIO m) => [(String, [String] -> InputT m ())]
commands = zip commandNames [performSet, performGet]
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27349748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档