我是haskell和函数式编程的新手。这可能是一件非常简单的事情,但我在搜索时找不到答案。
我在这里有这个功能:
main :: IO ()
main = print =<< (`rnd_select` 6) =<< readNumbers
readNumbers :: IO [(Int,Int,Int)]
readNumbers = makeTriples . map rInt . words <$> readFile "somefile"
rInt :: String -> Int
rInt = read
makeTriples :: [a] -> [(a,a,a)]
makeTriples [] = []
makeTriples (x:y:z:zs) = (x,y,z) : makeTriples zs
rnd_select :: [a] -> Int -> IO [a]
rnd_select _ 0 = return []
rnd_select [] _ = return []
rnd_select xs count = do r <- randomRIO (0, (length xs)-1)
rest <- rnd_select (removeAt (r+1) xs) (count-1)
return ((xs!!r) : rest)
removeAt :: Int -> [a] -> [a]
removeAt _ [] = []
removeAt 1 (x:xs) = xs
removeAt k (x:xs) = let r = removeAt (k - 1) xs in x:r
这包含在IO-monad中,当我想在值上使用函数时,这就变得很难。
这里我使用bind函数将输入应用于rnd_select函数:
(`rnd_select` 6) =<< readNumbers
但为了做到这一点,我必须将其部分应用于某个值。
我觉得它看起来不太好,如果函数有更多变量,我不知道怎么做。
所以我想知道是否有更好的方法将值应用于这些函数?
答案 0 :(得分:4)
除了定义函数,使得省略的参数是最后一个参数,以便您可以编写
foobar = baz . foo 5 17 29 . bar
你可以使用lambda来排除除了最后一个
之外的参数foobar = baz . (\x -> foo 5 17 x 29 41) . bar
但是对于只有两个参数的情况,flip
是一个不错的选择,
main = print =<< flip rnd_select 6 =<< readNumbers
答案 1 :(得分:1)
交换rnd_select
个参数,或使用flip rnd_select 6 =<< readNumbers
。