【问题标题】:No instance for Show arising from a use in "main" level没有因在“主要”级别使用而产生的 Show 实例
【发布时间】:2016-08-24 08:27:28
【问题描述】:

我有一个使用 UU.Parsing 库读取文件和解析的代码,该库返回一个抽象的 sintax 树并显示在屏幕上。

我在源自 tokensParserToByteStringapplyParser 的函数中使用 parseIO(UU.Parsing lib) 和继承的签名直到 main.我修复了签名,但我的问题出在 ma​​in 函数中。我在签名中添加了实例 Show 但出现下一个编译错误:

No instance for (Show (IO J2s)) arising from a use of ‘main’
In the expression: main
When checking the type of the IO action ‘main’

完整的错误信息是:

$ cabal build
Building java2scala-1.0...
Preprocessing library java2scala-1.0...
In-place registering java2scala-1.0...
Preprocessing executable 'java2scala' for java2scala-1.0...
Preprocessing executable 'test' for java2scala-1.0...
[5 of 5] Compiling Main             ( test/Main.hs, dist/build/test/test-tmp/Main.o )

test/Main.hs:27:1:
    No instance for (Show (IO J2s)) arising from a use of ‘main’
    In the expression: main
    When checking the type of the IO action ‘main’

关于这个问题的一些想法?

主模块

{-# LANGUAGE FlexibleContexts #-}
module Main where

import UU.Parsing
...
import Content

main :: (Show (IO J2s)) => IO()
main = do f <- getLine
      let command = test f
      command

test :: (Show (IO J2s)) => String -> IO()
test "testparser" = testParser

测试模块

{-# LANGUAGE FlexibleContexts #-}
module J2s.Parser.Test where

import Content
import J2s.Ast.Sintax
import J2s.Parser
import UU.Parsing
...

testParser :: (Show (IO J2s)) => IO()
testParser  = (runSafeIO $ runProxy $ runEitherK $
                contentsRecursive "path/of/my/tests" />/ handlerParser) :: (Show (IO J2s)) => IO()

内容模块

{-# LANGUAGE FlexibleContexts #-}
module Content where

import Control.Monad(forM, liftM)
import System.Directory (doesDirectoryExist, getDirectoryContents)
import System.FilePath ((</>), splitExtension, splitFileName)
import J2s.Parser
import J2s.Ast.Sintax
import UU.Parsing

import Control.Monad (when, unless)
import Control.Proxy
import Control.Proxy.Safe hiding (readFileS)

import J2s.Scanner.Token
import Text.Show

import UU.Parsing


contentsRecursive
     :: (CheckP p)
     => FilePath -> () -> Producer (ExceptionP p) FilePath SafeIO ()
contentsRecursive path () = loop path
   where
     loop path = do
         contents path () //> \newPath -> do
             respond newPath
             isDir <- tryIO $ doesDirectoryExist newPath
             let isChild = not $ takeFileName newPath `elem` [".", ".."]
             when (isDir && isChild) $ loop newPath


applyParser :: (Proxy p, Show (IO J2s)) => String -> Consumer p B.ByteString IO ()
applyParser path = runIdentityP loop
  where
    loop = do
        bs <- request ()
        let sc = classify  (initPos path) (B8.unpack bs)
        lift $  B8.putStrLn (tokensParserToByteString sc)

tokensParserToByteString :: (Show (IO J2s)) =>  [Token] -> B.ByteString
tokensParserToByteString tokens = B8.pack(show (parseIO pJ2s tokens))


handlerParser :: (CheckP p, Show (IO J2s)) => FilePath -> Session (ExceptionP p) SafeIO ()
handlerParser path = do
    canRead <- tryIO $ fmap readable $ getPermissions path
    isDir   <- tryIO $ doesDirectoryExist path
    isValidExtension <- tryIO $ evaluate ((snd (splitExtension path) == ".java" || snd (splitExtension path) == ".mora") && (snd (splitFileName path) /= "EncodeTest.java") && (snd (splitFileName path) /= "T6302184.java") && (snd (splitFileName path) /= "Unmappable.java"))
    when (not isDir && canRead && isValidExtension) $
        (readFileSP 10240 path >-> try . applyParser) path


readFileSP
:: (CheckP p)
=> Int -> FilePath -> () -> Producer (ExceptionP p) B.ByteString SafeIO ()
readFileSP chunkSize path () =
    bracket id (openFile path ReadMode) hClose $ \handle -> do
        let loop = do
                eof <- tryIO $ hIsEOF handle
                unless eof $ do
                    bs <- tryIO $ B.hGetSome handle chunkSize
                    respond bs
                    loop
        loop

【问题讨论】:

  • 能否显示完整的错误信息?
  • This 可能会有所帮助。
  • AFAIK,main 的类型必须为 main :: IO()main :: [String] -&gt; IO()
  • 完整的错误信息是: > cabal build Building java2scala-1.0... 预处理库 java2scala-1.0... 就地注册 java2scala-1.0... 为 java2scala- 预处理可执行文件“java2scala” 1.0...为 java2scala-1.0 预处理可执行文件“test”... [5 of 5] 编译 Main (test/Main.hs, dist/build/test/test-tmp/Main.o) test/Main.hs: 27:1: (Show (IO J2s)) 没有因使用“main”而产生的实例在表达式中:main 检查 IO 操作“main”的类型时
  • 请编辑您的问题,以便使用正确的格式。

标签: haskell pipe


【解决方案1】:

Show (IO J2s) =&gt; IO () 这样的签名几乎没有意义。这表达的基本意思是“如果宇宙被精心设计成IO J2s 有一个Show 实例,我给你一个IO () 动作”。好吧,如果宇宙有这个属性,那么现在就给我们IO () 行动。 Keep nasty chipsconstraints
只有将约束应用到类型变量时,约束才真正有意义,也就是说,如果你编写的代码对几种不同的类型具有多态性,但不是所有类型。 (如CheckP p)。但是应用于具体类型的约束只不过是延迟类型错误而已。

IO J2s 没有Show 实例。它不能有这样的实例:这是一个IO 动作。它可能是一个完整的子程序,可能会执行昂贵的计算、调用商业第三方库代码、发射一些导弹......并且只有在最后返回一个J2s 值。您如何期望将如此复杂的事物的所有信息打包成一个简单的字符串?

Show 实例可能是J2s。如果您无论如何都在IO monad 中并且有一个IO J2s 操作,您可以随时通过monad 绑定该操作从中获取J2s 值(即执行子程序) 并仅显示 J2s 值。在你的情况下:

tokensParserToByteString :: [Token] -> IO B.ByteString
tokensParserToByteString tokens = fmap (B8.pack . show) $ parseIO pJ2s tokens

如果你对 IO 函子中的 fmapping 感到困惑,这相当于

tokensParserToByteString :: [Token] -> IO B.ByteString
tokensParserToByteString tokens = do
     j2sValue <- parseIO pJ2s tokens
     return . B8.pack $ show j2sValue

当然你需要适应applyParser,因为tokensParserToByteString现在是IO动作。使用=&lt;&lt; operator 很容易:

applyParser :: Proxy p => String -> Consumer p B.ByteString IO ()
applyParser path = runIdentityP loop
  where
    loop = do
        bs <- request ()
        let sc = classify  (initPos path) (B8.unpack bs)
        lift $ B8.putStrLn =<< tokensParserToByteString sc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多