Reputation: 67
I am a newbie to haskell and functional programming. This might be a very simple thing, but I haven't found an answer while searching.
I have this function main here:
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
This is wrapped in the IO-monad and that is what makes it hard when i want to use functions on the values.
Here i use the bind function to apply the input to the rnd_select function:
(`rnd_select` 6) =<< readNumbers
But in order to do that I have to partially apply it to a value.
I don't think it looks very good and I don't know how I would do it if the function had more variables.
So I want to know if there is a nicer way to apply values to functions such as these?
Upvotes: 3
Views: 1104
Reputation: 129774
Either swap rnd_select
arguments, or use flip rnd_select 6 =<< readNumbers
.
Upvotes: 1
Reputation: 183878
Apart from defining the function such that the argument left out is the last argument, so that you can write
foobar = baz . foo 5 17 29 . bar
you can use a lambda to leave out arguments other than the last,
foobar = baz . (\x -> foo 5 17 x 29 41) . bar
but for the case of just two arguments, flip
is a nice alternative,
main = print =<< flip rnd_select 6 =<< readNumbers
Upvotes: 4