我最近开始学习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) 我正在尝试在我正在使用的Haskell项目中使用"citation-resolve"包,但是我无法在实际代码中使用EitherT.我知道他们是monad变形金刚,我想我明白这意味着什么,但我似乎无法真正弄清楚如何使用它们.代表我正在尝试做的玩具示例如下:
module Main where
import Text.EditDistance
import Text.CSL.Input.Identifier
import Text.CSL.Reference
import Control.Monad.Trans.Class
import Control.Monad.Trans.Either
main = do
putStrLn "Resolving definition"
let resRef = runEitherT $ resolveEither "doi:10.1145/2500365.2500595"
case resRef of
Left e -> do
putStrLn ("Got error: "++ e)
Right ref -> do
putStrLn ("Added reference to database: "++ (show ref))
Run Code Online (Sandbox Code Playgroud)
这里resolveEither有类型:
resolveEither :: (HasDatabase s,
Control.Monad.IO.Class.MonadIO m,
mtl-2.1.3.1:Control.Monad.State.Class.MonadState s m)
=> String -> EitherT String m Reference
Run Code Online (Sandbox Code Playgroud)
并runEitherT $ resolveEither "ref"有类型:
runEitherT $ resolveEither "ref" …Run Code Online (Sandbox Code Playgroud) 我有以下函数生成1024的倍数的随机字符串:
import System.Random
rchars :: Int -> [IO Char]
rchars n = map (\_ -> randomRIO ('a', 'z')) [n | n <- [0..n]] -- a wasteful "iteration"-like func
rstr :: Int -> IO String
rstr n = sequence $ rchars (1024 * n)
Run Code Online (Sandbox Code Playgroud)
我想使用Spock将其暴露给Web,例如:
import Data.Monoid
import Data.Text
import Lib
import Web.Spock.Safe
main :: IO ()
main =
runSpock 8080 $ spockT id $
do get root $
redirect "/data/1"
get ("data" <//> var) $ \n ->
do
str <- …Run Code Online (Sandbox Code Playgroud) 我在IO上下文中有几种数据类型,如:
a :: IO String
b :: IO FilePath
c :: String -> IO String
Run Code Online (Sandbox Code Playgroud)
我想把它们放在一个数据对象中,如:
data Configdata = Configdata String FilePath (String -> String)
Run Code Online (Sandbox Code Playgroud)
因此,我不必从IO上下文中获取自己的每个值,而只是从中获取IO Configdata.
我没有解决方案的关键点是我如何转变String -> IO String为IO (String -> String).Hoogle没有给我任何能够做到这一点的功能.
我不确定它是否可能甚至不可能,因为函数的输入可能是无限的.
有人有解决方案或解释为什么不可能?我知道使用列表而不是函数是一个选项,但我更愿意使用函数.
我一直试图弄清楚如何在IO monad中进行递归.我熟悉使用纯函数进行递归,但是无法将这些知识传递给IO monad.
使用纯函数递归
我很喜欢用纯函数进行递归,例如foo下面的函数.
foo (x:y:ys) = foo' x y ++ foo ys
Run Code Online (Sandbox Code Playgroud)
一个带有IO [String]输出
的函数我做了一个像goo下面这样的函数,它可以满足我的需求并具有IO输出.
goo :: String -> String -> IO [String]
goo xs ys = goo' xs ys
Run Code Online (Sandbox Code Playgroud)
试图在IO monad中获取递归
当我尝试在IO monad中进行递归时(例如,"主"函数)我不能.我抬头一看liftM,replicateM和撤消最IO <-操作或功能.我想要一个IO monad hoo或者hoo'(为随后的乱码道歉).
hoo :: [String] -> IO [String]
hoo (xs:ys:yss) = do
let rs = goo xs ys ++ hoo yss
return rs
Run Code Online (Sandbox Code Playgroud)
要么
hoo' :: [String] -> IO [String]
hoo' …Run Code Online (Sandbox Code Playgroud) 我有一个像这样的字符串到IO的映射Map[String, IO[String]],我想将其转换为IO[Map[String, String]].怎么做?
我在 IO Monad 上有点挣扎。(仍然是 101 的学习者)
我相信我理解将“IO”与纯功能代码分离的绝佳理由,但这似乎使我的代码在使用时钟和环境属性时变得更加复杂。这是一个示例(与时钟相关):
timeZoneSeconds = liftA (60*) $ liftA timeZoneMinutes getCurrentTimeZone
Run Code Online (Sandbox Code Playgroud)
现在,我还有很多其他的东西与 timeZoneSeconds 相关——加、减、比较——在程序的其他地方,而且当 timeZoneSeconds 与其他位交互时,几乎我处理的所有事情都变成了“IO”,因此用liftAs填充我的代码。
所以基本上我看到我所有的纯代码都变成了 IO 脏代码。
在我看过的所有教学材料中,大部分关于 IO monad 的解释都是“读东西然后写东西”的一般类型,没有太多“计算东西”。
有没有推荐的方法来减少这种影响?
我是否应该重新定义我需要在“幕后”使用liftA 的所有操作符?
还是我应该继续下去?
以下(工作)Haskell 程序输出随机拼写:
import System.Random
spells =
[ "Abracadabra!"
, "Hocus pocus!"
, "Simsalabim!"
]
main :: IO()
main = do
spell <- (spells !!) <$> randomRIO (0, length spells - 1)
putStrLn spell
Run Code Online (Sandbox Code Playgroud)
然而,这个变量spell是非常无用的。它存储从法术列表中选择的随机字符串,但随后会立即传递给putStrLn函数并且不再使用。我尝试将两个 IO 操作合并为一行,如下所示:
main = putStrLn <$> (spells !!) <$> randomRIO (0, length spells - 1)
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
• Couldn't match type ‘IO ()’ with ‘()’
Expected type: Int -> ()
Actual type: Int -> IO ()
• In the first argument of ‘(<$>)’, …Run Code Online (Sandbox Code Playgroud) 我想知道如何IO [Int]在 GHCI 中映射一个。
?: :{
?| th :: IO [Int]
?| th = pure [1, 2, 3, 4]
?| :}
?: th
[1,2,3,4]
?: :t th
th :: IO [Int]
?: map (+2) th
• Couldn't match expected type ‘[b]’ with actual type ‘IO [Int]’
• In the second argument of ‘map’, namely ‘th’
In the expression: map (+ 2) th
Run Code Online (Sandbox Code Playgroud)
想要的结果:
?: res = map (+2) th -- <-- some working version of this
?: res …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一些 IO 包装的函数。
\n我当前的代码(有效)是:
\ngetUserHome :: IO String\ngetUserHome = do\n usr_id <- getRealUserID\n homeDirectory <$> getUserEntryForID usr_id\nRun Code Online (Sandbox Code Playgroud)\n我正在寻找一种更方便的表示法(不使用 -do关键字的表示法)。
没有任何 Monadic 沙拉我就写
\ngetUserHome = homeDirectory . getUserEntryForID . getRealUserID\nRun Code Online (Sandbox Code Playgroud)\n我猜想还有一个.尊重 Monad 的替代运算符..?但在我所有的寻找中,我还没有找到它。
我尝试过<$>,但这似乎不是我想要的:
src/Main.hs:49:21: error:\n \xe2\x80\xa2 Couldn\'t match type \xe2\x80\x98IO UserEntry\xe2\x80\x99 with \xe2\x80\x98UserEntry\xe2\x80\x99\n Expected type: UserID -> UserEntry\n Actual type: UserID -> IO UserEntry\n \xe2\x80\xa2 In the second argument of \xe2\x80\x98(<$>)\xe2\x80\x99, namely \xe2\x80\x98getUserEntryForID\xe2\x80\x99\n In the …Run Code Online (Sandbox Code Playgroud)