所以这个问题更多地是关于Monads(尤其是Fay),但是我的例子使用了IO monad.
我有一个函数,其中输入是一个字符串列表,我想逐个打印每个字符串.所以这是我的想法:
funct :: [String] -> ?
funct strs = do
map putStrLn strs
Run Code Online (Sandbox Code Playgroud)
但是不起作用,因为它返回一个类型[IO()].所以我的问题是,我将如何映射列表,并将其视为我在逐行执行函数,以典型的符号,迭代风格(如下所示)?
funct :: [String] -> IO ()
funct strs = do
putStrLn (strs !! 0)
putStrLn (strs !! 1)
...
Run Code Online (Sandbox Code Playgroud) 我仍在研究 Haskell,尤其是 IO monad。
我有一个目录路径列表,例如,
["/some/path", "/another/path", "/yet/another/path", "/still/more"]
并且我想将此列表映射到每个路径的完全限定内容列表中(没有.
和..
),如下所示:
["/some/path/file.1", "/some/path/somedir", "/some/path/file.2", "/another/path/file.a", "/another/path/a/directory", "/another/path/file.b", "/still/more/file.alpha", ...]
我想我可以用某种双映射来做到这一点,就像这样:
pathItems <- mapM (\pd -> MapM (\contents -> (pd </>) contents) (getDirectoryContents pd) pathDirs
但这不起作用。我得到的错误是这样的:
程序.hs:27:56: 无法将类型“[]”与“IO”匹配 预期类型:IO 字符 实际类型:文件路径 在表达式中: (pd </>) 内容 在‘mapM’的第一个参数中,即 `(\ 内容 -> (pd ) 内容)' 程序.hs:27:84: 无法匹配预期类型“[FilePath]” 实际类型为“IO [FilePath]” 在'mapM'的第二个参数中,即 `(getDirectoryContents pathDir)' 在表达式中: 地图M (\ 内容 -> (pd </>) 内容) (getDirectoryContents pd)
我已经使用该Parsec
库编写了一个文件解析器.我想使用Tasty
测试框架编写一个高级单元测试,以确保解析器正确解析某些给定的文件.
我在以下目录结构中有三个格式良好的文件:
path/to/files -+
|-> fileA
|-> fileB
|-> fileC
Run Code Online (Sandbox Code Playgroud)
我想要:
path/to/files
testCase
为每个文件创建一个文件,以确保成功解析文件的内容我设法构建了以下内容:
{-# LANGUAGE BangPatterns, FlexibleContexts #-}
module Test.MyParser
( testSuite
) where
import Control.Arrow ((&&&))
import Data.Map (Map,fromList,toList)
import System.Directory
import System.IO.Unsafe (unsafePerformIO) -- This is used for a hack
import Test.Tasty (TestTree,testGroup,withResource)
import Test.Tasty.HUnit
import Text.Parsec
-- | Determine if an Either is a Right or Left value
-- Useful for determining if a parse attempt was successful …
Run Code Online (Sandbox Code Playgroud) 这是我正在编写的特定于域的文件IO函数的摘录:
let
cp :: FilePath -> IO ()
cp "." = putStr "" -- OUCH!
cp ".." = putStr "" -- CRIKEY!
cp fname = custom logic here...
in mapM_ cp filepaths
Run Code Online (Sandbox Code Playgroud)
我理解mapM_
让我们放弃/忽略所有IO ()
结果,所以我想要一个更清洁的替代品putStr ""
---即.Haskell的"规范"方式来编写"一个不做任何事情的类型正确的无操作IO(或monad)表达式".
从我的新手阅读中我undefined
想到了,虽然这个编译并没有引起任何问题,但它会产生一个不需要的stdout打印main.hs: Prelude.undefined
(我在这里stack runghc main.hs
用作唯一的编码环境---它就足够了,但上面的代码将以递归的方式循环通过目录树:这将是(重新)了解更好,或更确切地说"正确"方式的好时机.
我正在使用该BlazeClientBuilder[IO].resource
方法来获取Client[IO]
. 现在,我想模拟客户端进行单元测试,但不知道该怎么做。有没有一个好的方法来嘲笑这个,我会怎么做?
class ExternalCall(val resource: Resource[IO, Client[IO]], externalServiceUrl: Uri) {
def retrieveData: IO[Either[Throwable, String]] = {
for {
req <- IO(Request[IO](Method.GET, uri = externalServiceUrl))
response <- resource.use(client => {
client.fetch[String](req)(httpResponse => {
if (!httpResponse.status.isSuccess)
throw new Exception(httpResponse.status.reason)
else
httpResponse.as[String]
})
})
} yield Right(response)
}
}
Run Code Online (Sandbox Code Playgroud)
来电代码
new ExternalCall(BlazeClientBuilder[IO](global).resource).retrieveData
Run Code Online (Sandbox Code Playgroud) 您好社区,感谢您的宝贵时间。
\n我有一个错误,我不确定错误是什么,但我认为问题是:\n没有从ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO)
到 的IO 转换器Web.Scotty.Internal.Types.ScottyT
。
但我想知道为什么编译器与ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO)
. 这就是为什么我只使用 String 并删除了所有出现的{-# LANGUAGE OverloadedStrings #-}
但仍然收到错误。另一方面,这应该是IO [String]
,不是吗?\n正如你所提到的,我真的不知道是什么ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO)
。
在另一个地方,我已经liftIO
成功使用了一个a -> IO String
函数。我想我也以同样的方式使用它们。
我想我慢慢地感觉到了 monad 是什么,但不太确定。我真的不知道为什么我必须使用一个lift
函数。
错误信息:
\n \xe2\x80\xa2 No instance for (MonadIO\n (Web.Scotty.Internal.Types.ScottyT\n text-1.2.4.1:Data.Text.Internal.Lazy.Text IO))\n arising from a use of \xe2\x80\x98liftIO\xe2\x80\x99\n \xe2\x80\xa2 In a stmt of a \'do\' block:\n paths <- liftIO $ getAllFilePaths2 path\n In the expression:\n do …
Run Code Online (Sandbox Code Playgroud) 考虑以下程序。
import Control.Monad.State
import Control.Monad.Catch
ex1 :: StateT Int IO ()
ex1 = do
modify (+10)
liftIO . ioError $ userError "something went wrong"
ex2 :: StateT Int IO ()
ex2 = do
x <- get
liftIO $ print x
ex3 :: StateT Int IO ()
ex3 = ex1 `onException` ex2
main :: IO ()
main = evalStateT ex3 0
Run Code Online (Sandbox Code Playgroud)
当我们运行程序时,我们得到以下输出。
$ runhaskell Test.hs
0
Test.hs: user error (something went wrong)
Run Code Online (Sandbox Code Playgroud)
但是,我预计输出如下。
$ runhaskell Test.hs
10
Test.hs: user error (something …
Run Code Online (Sandbox Code Playgroud) 我不太了解 Haskell 优化在内部是如何工作的,但我一直在使用过滤器,希望它们被优化为与 C++ 中的简单 if 等效的东西。例如
mapM_ print $ filter (\n -> n `mod` 2 == 0) [0..10]
Run Code Online (Sandbox Code Playgroud)
将编译成相当于
for (int i = 0; i < 10; i++)
if (i%2 == 0)
printf("%d\n", i);
Run Code Online (Sandbox Code Playgroud)
对于长列表(10 000 000 个元素),基本列表似乎是正确的,filter
但如果我使用 monadic ,则存在巨大差异filterM
。我为此速度测试编写了一段代码,很明显,filterM
使用when
.
import Data.Array.IO
import Control.Monad
import System.CPUTime
main :: IO ()
main = do
start <- getCPUTime
arr <- newArray (0, 100) 0 :: IO (IOUArray Int Int)
let
okSimple i = …
Run Code Online (Sandbox Code Playgroud) 我最近开始学习Haskell.我正在尝试编写一个选择数组的随机元素的程序:
import System.Random
randomInt :: (Int, Int) -> IO Int
randomInt range = randomRIO range :: IO Int
choseRandom :: [a] -> a
choseRandom list =
length list
>>=
(\l -> randomInt(0,l-1))
>>=
(\num -> (list !! num))
main :: IO ()
main = undefined
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Build FAILED
C:\Users\User\Haskell\Real\src\Main.hs: line 7, column 9:
Couldn't match expected type `IO Int' with actual type `Int'
In the return type of a call of `length'
In the first argument of `(>>=)', namely `length …
Run Code Online (Sandbox Code Playgroud) 我正在从用户必须输入的输入中读取几行内容:
main :: IO ()
main = do
let size = 3
arr <- replicateM size getLine
let pairs = map parsePair arr
print pairs
Run Code Online (Sandbox Code Playgroud)
为什么我可以map parsePair arr
在单独的行上做而不是在同一行上做,像这样:
arr <- map parsePair (replicateM size getLine)
Run Code Online (Sandbox Code Playgroud)
这样做,我得到了错误?:
• Couldn't match type ‘[]’ with ‘IO’
Expected type: IO [Int]
Actual type: [[Int]]
Run Code Online (Sandbox Code Playgroud)
为了给您更多细节,这里是parsePair
:
parsePair string = map parseInt $ words string
parseInt :: String -> Int
parseInt s = read s :: Int
Run Code Online (Sandbox Code Playgroud) io-monad ×10
haskell ×9
monads ×7
do-notation ×1
exception ×1
hunit ×1
io ×1
lifting ×1
mockito ×1
optimization ×1
performance ×1
scala ×1
scala-cats ×1
scotty ×1
state-monad ×1
types ×1
unit-testing ×1