So I have a function in Haskell that I've simplified for the purpose of asking this question:
import Data.Foldable
import Data.Set
myFn :: Int -> Set Int
myFn a
| a <= 0 = singleton 1
| otherwise = foldMap helper (myFn (a - 1))
helper :: Int -> Set Int
helper a = insert (a + 2) (singleton a)
main :: IO ()
main = print . Data.Set.toList $ myFn 5
I want to have myFn's dependency on helper to be put into a Reader, since inversion of control allows me to switch implementations in my tests:
import Control.Monad.Reader
import Data.Foldable
import Data.Set
data MyEnv = MyEnv { helper' :: Int -> Set Int }
type MyReader = Reader MyEnv
myFn :: Int -> MyReader (Set Int)
myFn a
| a <= 0 = return $ singleton 1
| otherwise = do
myFn' <- myFn (a - 1)
helper'' <- asks helper'
return (foldMap helper'' myFn')
helper :: Int -> Set Int
helper a = insert (a + 2) (singleton a)
main :: IO ()
main =
let
myEnv = MyEnv helper
in
print . Data.Set.toList $ runReader (myFn 5) myEnv
This works fine, except I don't like these three lines in particular:
myFn' <- myFn (a - 1)
helper'' <- asks helper'
return (foldMap helper'' myFn')
I feel like there should be a way to lift foldMap in the same way as mapM is a lifted version of map through its composition with sequence. Ideally, I would like those three lines to collapse down to one:
foldMapM helper'' (partitions (n - 1))
Assuming that: helper'' :: Int -> MyReader (Set Int)
This would of course require a foldMapM function with a signature similar to:
foldMapM
:: (Monad m, Foldable t, Monoid n)
=> (a -> m n)
-> m (t a)
-> m n
I have tried so many things, but I just cannot seem to implement this function, though! Can anyone help?
Basically, you would like to create Monad m => m a -> m b -> m c from a -> b -> c. That's exactly what liftM2 (from Control.Monad) does:
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
Promote a function to a monad, scanning the monadic arguments from
left to right. For example,
liftM2 (+) [0,1] [0,2] = [0,2,1,3]
liftM2 (+) (Just 1) Nothing = Nothing
Therefore, it's as simple as using liftM2 foldMap:
myFn :: Int -> MyReader (Set Int)
myFn a
| a <= 0 = return $ singleton 1
| otherwise = liftM2 foldMap (asks helper') (myFn (a - 1))
Alternatively you can use <$> and <*> from Control.Applicative if you don't like additional parentheses:
myFn :: Int -> MyReader (Set Int)
myFn a
| a <= 0 = return $ singleton 1
| otherwise = foldMap <$> asks helper' <*> myFn (a - 1)
For more information, have a look at the Typeclassopedia.
Related
In this program , I wanted to ask the user about number of cards and draw that number of cards from a deck (see below) and tell the user the cards and the
"total" of those cards. In this case, I mean a blackjack count of up to 21, with
counts over 21 returning Nothing. A blackjack count counts 2-10 as its face value, jacks,
queens and kings count as 10 and aces count as 1 or 11. I need two functions:
drawHand :: Int ->Deck ->([Card],Deck) and totalCards :: [Card] ->Maybe Int
import Data.List
import Data.Random
drawHand :: Int -> Deck -> ([Card], Deck)
totalCards :: [Card] -> Maybe Int
main = do
putStrLn "How many cards?"
Random :: MonadRandom m => Deck-> m Deck
Random ran = runRVar (shuffle deck) StdRandom
Random <- getLine
putStrLn "Hand of [] totalCards: " ++ totalCards
error:
Failed to load interface for ‘Data.Random’
Perhaps you meant Data.Ratio (from base-4.9.0.0)
Use -v to see a list of the files searched for.
PLEASE HELP ME
At this point we have no information about the Card and Deck data types.
However, it seems that the problem at hand is to randomly extract M cards from an initial deck of N cards.
If this interpretation of the question is correct, we can thus use the Rand monad constructor, and start by defining a monadic action that transfers just one card from the right deck to the left deck.
As we have no information about the types in use, we will assume that the “cards” are denoted by plain numbers, from 0 to 51.
Next, we define an action moving M cards recursively, moving one card and then calling ourselves with an (M-1) argument. For M=0, we define the action as a no-op.
This would be the monadic code:
import System.Random
import Control.Monad.Random
moveOneCardLeft :: RandomGen g => ([a],[a]) -> Rand g ([a],[a])
moveOneCardLeft (deck, rest) =
do
let remCount = length rest
choice <- getRandomR (0, (remCount-1))
let (top, bot) = splitAt choice rest
return $ ((head bot) : deck, top ++ (tail bot))
moveSomeCardsLeft :: RandomGen g => Int -> ([a],[a]) -> Rand g ([a],[a])
moveSomeCardsLeft 0 (deck, rest) = return (deck, rest) -- unchanged
moveSomeCardsLeft n (deck, rest) =
do
(deck1, rest1) <- moveOneCardLeft (deck, rest)
(deck2, rest2) <- moveSomeCardsLeft (n-1) (deck1, rest1)
return (deck2, rest2)
extractSomeCards :: RandomGen g => Int -> [a] -> Rand g ([a], [a])
extractSomeCards n xs =
do
(deck, rest) <- moveSomeCardsLeft n ([], xs)
return (deck, rest)
Next, the pure code and some tentative game-related utility functions:
drawSomeCards :: RandomGen g => g -> Int -> [a] -> (([a], [a]), g)
drawSomeCards gen0 n xs = runRand (extractSomeCards n xs) gen0
cardValue :: Int -> Int
cardValue n = let rank = mod n 13
in if (rank < 10) then (rank+1)
else {- Jack Queen King -} 10
deckValue :: [Int] -> Int
deckValue cards = sum (map cardValue cards)
totalOfCards :: [Int] -> Maybe Int
totalOfCards cards =
let s = deckValue cards
in if (s <= 21) then (Just s) else Nothing
Finally, the user test code:
main = do
let wholeDeck = [0..51]
randomSeed = 4243
gen0 = mkStdGen randomSeed
putStrLn "How many cards ?"
inLine <- getLine
let count = (read inLine :: Int)
putStrLn $ "Want to extract " ++ (show count) ++ " cards."
let ((deck, rest), gen1) = drawSomeCards gen0 count wholeDeck
sumw = sum wholeDeck
suma = sum deck
sumb = sum rest
sum0 = (suma + sumb) - sumw
putStrLn $ "Must be zero: " ++ (show sum0) -- sanity check
putStrLn $ "deck: " ++ (show deck)
putStrLn $ "rest: " ++ (show rest)
putStrLn $ "Deck value: " ++ (show $ deckValue deck)
Program execution:
$ q67025780.x
How many cards ?
10
Want to extract 10 cards.
Must be zero: 0
deck: [8,47,38,49,4,31,9,30,28,23]
rest: [0,1,2,3,5,6,7,10,11,12,13,14,15,16,17,18,19,20,21,22,24,25,26,27,29,32,33,34,35,36,37,39,40,41,42,43,44,45,46,48,50,51]
Deck value: 77
$
Note: if deemed appropriate, the above code beyond moveOneCardLeft can be simplified using the nest :: Monad m => Int -> (a -> m a) -> a -> m a function from the Control.Monad.HT package.
Like this:
import Control.Monad.HT (nest)
moveOneCardLeft :: RandomGen g => ([a],[a]) -> Rand g ([a],[a])
moveOneCardLeft (deck, rest) =
do
let remCount = length rest
choice <- getRandomR (0, (remCount-1))
let (top, bot) = splitAt choice rest
return $ ((head bot) : deck, top ++ (tail bot))
drawSomeCards :: RandomGen g => g -> Int -> [a] -> (([a], [a]), g)
drawSomeCards gen0 n xs = let action = nest n moveOneCardLeft ([], xs)
in runRand action gen0
I am currently taking a class in Haskell and am having a bit of trouble understanding how functions are passed as parameters. For this assignment, we were tasked with creating a program that would evaluate expressions. To reduce boiler plating, I wanted to abstract the function by creating a helper function that would take in an operator as an input and return the result
Main Function:
eval :: EDict -> Expr -> Maybe Double
eval _ (Val x) = Just x
eval d (Var i) = find d i
eval d (Add x y) = evalOp d (+) x y
eval d (Mul x y) = evalOp d (*) x y
eval d (Sub x y) = evalOp d (-) x y
Helper Function:
evalOp:: EDict -> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
let r = eval d x
s = eval d y
in case (r, s) of
(Just m, Just n) -> Just (m `op` n)
_ -> Nothing
Other definitions
data Expr
= Val Double
| Add Expr Expr
| Mul Expr Expr
| Sub Expr Expr
| Dvd Expr Expr
| Var Id
| Def Id Expr Expr
deriving (Eq, Show)
type Dict k d = [(k,d)]
define :: Dict k d -> k -> d -> Dict k d
define d s v = (s,v):d
find :: Eq k => Dict k d -> k -> Maybe d
find [] _ = Nothing
find ( (s,v) : ds ) name | name == s = Just v
| otherwise = find ds name
type EDict = Dict String Double
I looked into how +,-, and * are to be passed into other functions and found that these operators are defined by the following definition:
ghci> :t (*)
(*) :: (Num a) => a -> a -> a
However, when I run my code I get the following compilation error:
Illegal polymorphic or qualified type: Num a => a -> a -> a
Perhaps you intended to use RankNTypes or Rank2Types
In the type signature for ‘evalOp’:
evalOp :: EDict
-> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double
I am not really sure why this is happening as I gave my function the proper parameters as defined by Haskell. Any help would be greatly appreciated as I am still very new to the language.
Right now, your Expr data type is constrained to Double-valued expressions, so there is no need to deal with polymorphism.
evalOp:: EDict -> (Double -> Double -> Double) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
let r = eval d x
s = eval d y
in case (r, s) of
(Just m, Just n) -> Just (m `op` n)
_ -> Nothing
(+) :: Num a => a -> a -> a is a valid argument for evalOp, because its type can be "restricted" to Double -> Double -> Double.
> let f :: Double -> Double -> Double; f = (+)
> f 3 5
8.0
If your expression type were parameterized, then you would put a Num a constraint on your functions (not just on the arguments that involve a, because you want the same a throughout the function).
data Expr a
= Val a
| Add (Expr a) (Expr a)
| Mul (Expr a) (Expr a)
| Sub (Expr a) (Expr a)
| Dvd (Expr a) (Expr a)
| Var Id
| Def Id (Expr a) (Expr a)
deriving (Eq, Show)
type EDict a = Dict String a
evalOp:: Num a => EDict a -> (a -> a -> a) -> Expr a -> Expr a -> Maybe a
evalOp d op x y =
let r = eval d x
s = eval d y
in case (r, s) of
(Just m, Just n) -> Just (m `op` n)
_ -> Nothing
eval :: Num a => EDict a -> Expr a -> Maybe a
eval _ (Val x) = Just x
eval d (Var i) = find d i
eval d (Add x y) = evalOp d (+) x y
eval d (Mul x y) = evalOp d (*) x y
eval d (Sub x y) = evalOp d (-) x y
The error is telling you that you cannot nest a type qualifier inside one of the types in your function chain. Instead, put all of the qualifiers at the beginning of the type signature:
evalOp:: (Num a) => EDict -> (a -> a -> a) -> Expr -> Expr -> Maybe Double
See Haskell - Illegal Polymorphic type? for a more thorough discussion.
I want to merge two functions into one.
The functions are
data Dice = Stone Char deriving (Show, Eq)
calculateScore :: [Dobbelsteen] -> Int
calculateScore xs = sum[giveValueDice x | x <- xs]
giveValueDice :: Dice -> Int
giveValueDice (Stone d) = if d == 'W' then 5 else digitToInt d
Normally, I would just copy one line into the first function en change a little bit to make the syntax correct. But here I am kinda lost how to do this
As you've already noticed, you can't just directly inline here; the reason for this is that you're pattern matching on Stone in giveValueDice. This pattern matching can be moved inside the right side of the list comprehension:
calculateScore :: [Dobbelsteen] -> Int
calculateScore xs = sum[if d == 'W' then 5 else digitToInt d | (Stone d) <- xs]
Another method for merging these two functions is using a where clause, which 'merges' one function into another while keeping them distince:
calculateScore :: [Dobbelsteen] -> Int
calculateScore xs = sum[giveValueDice x | x <- xs]
where
giveValueDice :: Dice -> Int
giveValueDice (Stone d) = if d == 'W' then 5 else digitToInt d
I'm completely lost on this. It was explained that functions are right justified so that let add x y = x + y;; has a function type of int -> int -> int or int -> (int -> int).
I'm not sure how I'd define a function of type (int -> int) -> int. I was thinking I'd have the first argument be a function that passes in an int and returns an int. I've tried:
let add = fun x y -> x + y --- int -> int -> int
let add = fun f x = (f x) + 3 --- ('a -> int) -> 'a -> int
What about
let eval (f: int -> int) :int = f 0
?
fun x -> (x 1) + 1;;
- : (int -> int) -> int = <fun>
or
let foo f = (f 1) + 1;;
val foo : (int -> int) -> int = <fun>
it works like
foo (fun x -> x + 1);;
- : int = 3
Your questions is highly associated with the notion of Currying.
But before that, let me say that if you want to write a function that needs a parameter to be a function, you could declare a normal function, and just use its parameter like a function. No need to complicate it. See the ex:
let f x = x(10) + 10
Now comes the currying part. In OCaml, the parameters are semantically evaluated just one at a time, and after evaluating an argument, an anonymous function is returned. This is important because it lets you supply part of the arguments of a function, creating effectively a new function (which is called Partial Application).
In the example bellow, I use + as a function (parenthesis around an operator turn it to a normal function), to create an increment function. And apply it to the previous f function.
let incr = (+) 1
f incr
The code evaluates to f incr = incr(10) + 10 = 21
This link has more information on the topic applied to OCaml.
The question is similar to this question. However, this one is about exceptions, not about lazy I/O.
Here is a test:
{-# LANGUAGE ScopedTypeVariables #-}
import Prelude hiding ( catch )
import Control.Exception
fooLazy :: Int -> IO Int
fooLazy m = return $ 1 `div` m
fooStrict :: Int -> IO Int
fooStrict m = return $! 1 `div` m
test :: (Int -> IO Int) -> IO ()
test f = print =<< f 0 `catch` \(_ :: SomeException) -> return 42
testLazy :: Int -> IO Int
testLazy m = (return $ 1 `div` m) `catch` \(_ :: SomeException) -> return 42
testStrict :: Int -> IO Int
testStrict m = (return $! 1 `div` m) `catch` \(_ :: SomeException) -> return 42
So I wrote two functions fooLazy which is lazy and fooStrict which is strict, also there is two tests testLazy and testStrict, then I try to catch division by zero:
> test fooLazy
*** Exception: divide by zero
> test fooStrict
42
> testLazy 0
*** Exception: divide by zero
> testStrict 0
42
and it fails in lazy cases.
The first thing that comes to mind is to write a version of the catch function that force the evaluation on its first argument:
{-# LANGUAGE ScopedTypeVariables #-}
import Prelude hiding ( catch )
import Control.DeepSeq
import Control.Exception
import System.IO.Unsafe
fooLazy :: Int -> IO Int
fooLazy m = return $ 1 `div` m
fooStrict :: Int -> IO Int
fooStrict m = return $! 1 `div` m
instance NFData a => NFData (IO a) where
rnf = rnf . unsafePerformIO
catchStrict :: (Exception e, NFData a) => IO a -> (e -> IO a) -> IO a
catchStrict = catch . force
test :: (Int -> IO Int) -> IO ()
test f = print =<< f 0 `catchStrict` \(_ :: SomeException) -> return 42
testLazy :: Int -> IO Int
testLazy m = (return $ 1 `div` m) `catchStrict` \(_ :: SomeException) -> return 42
testStrict :: Int -> IO Int
testStrict m = (return $! 1 `div` m) `catchStrict` \(_ :: SomeException) -> return 42
it seems to work:
> test fooLazy
42
> test fooStrict
42
> testLazy 0
42
> testStrict 0
42
but I use the unsafePerformIO function here and this is scary.
I have two questions:
Can one be sure that the catch function always catches all exceptions, regardless of the nature of it first argument?
If not, is there a well-known way to deal with this kind of problems? Something like the catchStrict function is suitable?
UPDATE 1.
This is a better version of the catchStrict function by nanothief:
forceM :: (Monad m, NFData a) => m a -> m a
forceM m = m >>= (return $!) . force
catchStrict :: (Exception e, NFData a) => IO a -> (e -> IO a) -> IO a
catchStrict expr = (forceM expr `catch`)
UPDATE 2.
Here is another 'bad' example:
main :: IO ()
main = do
args <- getArgs
res <- return ((+ 1) $ read $ head args) `catch` \(_ :: SomeException) -> return 0
print res
It should be rewritten like this:
main :: IO ()
main = do
args <- getArgs
print ((+ 1) $ read $ head args) `catch` \(_ :: SomeException) -> print 0
-- or
--
-- res <- return ((+ 1) $ read $ head args) `catchStrict` \(_ :: SomeException) -> return 0
-- print res
--
-- or
--
-- res <- returnStrcit ((+ 1) $ read $ head args) `catch` \(_ :: SomeException) -> return 0
-- print res
--
-- where
returnStrict :: Monad m => a -> m a
returnStrict = (return $!)
UPDATE 3.
As nanothief noticed, there is no guarantee that the catch function always catch any exception. So one need to use it carefully.
Few tips on how to solve related problems:
Use ($!) with return, use forceM on the first argument of catch, use the catchStrict function.
I also noticed that sometimes people add some strictness to instances of their transformers.
Here is an example:
{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances
, MultiParamTypeClasses, UndecidableInstances, ScopedTypeVariables #-}
import System.Environment
import Prelude hiding ( IO )
import qualified Prelude as P ( IO )
import qualified Control.Exception as E
import Data.Foldable
import Data.Traversable
import Control.Applicative
import Control.Monad.Trans
import Control.Monad.Error
newtype StrictT m a = StrictT { runStrictT :: m a } deriving
( Foldable, Traversable, Functor, Applicative, Alternative, MonadPlus, MonadFix
, MonadIO
)
instance Monad m => Monad (StrictT m) where
return = StrictT . (return $!)
m >>= k = StrictT $ runStrictT m >>= runStrictT . k
fail = StrictT . fail
instance MonadTrans StrictT where
lift = StrictT
type IO = StrictT P.IO
instance E.Exception e => MonadError e IO where
throwError = StrictT . E.throwIO
catchError m h = StrictT $ runStrictT m `E.catch` (runStrictT . h)
io :: StrictT P.IO a -> P.IO a
io = runStrictT
It is essentially the identity monad transformer, but with strict return:
foo :: Int -> IO Int
foo m = return $ 1 `div` m
fooReadLn :: Int -> IO Int
fooReadLn x = liftM (`div` x) $ liftIO readLn
test :: (Int -> IO Int) -> P.IO ()
test f = io $ liftIO . print =<< f 0 `catchError` \(_ :: E.SomeException) -> return 42
main :: P.IO ()
main = io $ do
args <- liftIO getArgs
res <- return ((+ 1) $ read $ head args) `catchError` \(_ :: E.SomeException) -> return 0
liftIO $ print res
-- > test foo
-- 42
-- > test fooReadLn
-- 1
-- 42
-- ./main
-- 0
Firstly (I'm not sure if you know this already), the reason the catch doesn't work with the lazy case is the
1 `div` 0
expression isn't evaluated until it is needed, which is inside the print function. However, the catch method is applied just to the f 0 expression, not the whole print =<< f 0 expression, so the exception isn't caught. If you did:
test f = (print =<< f 0) `catch` \(_ :: SomeException) -> print 42
instead, it works correctly in both cases.
If you want to make a catch statement though that forces complete evaluation of the IO result, instead of making a new instance of NFData, you could write a forceM method, and use that in the catchStrict method:
forceM :: (Monad m, NFData a) => m a -> m a
forceM m = m >>= (return $!) . force
catchStrict :: (Exception e, NFData a) => IO a -> (e -> IO a) -> IO a
catchStrict expr = (forceM expr `catch`)
(I'm a bit surprised that forceM isn't inside the Control.DeepSeq library)
Regarding your comment:
No, the rule is the exception is only thrown when the value is computed, and that is only done when it is needed by haskell. And if haskell can delay the evaluation of something it will.
An example test function that doesn't use $!, but still causes an exception straight away (so the normal catch will catch the divide by zero exception) is:
fooEvaluated :: Int -> IO Int
fooEvaluated m = case 3 `div` m of
3 -> return 3
0 -> return 0
_ -> return 1
Haskell is forced to evaluated the "3 `div` m" expression, as it needs to match the result against 3 and 0.
As a last example, the following doesn't throw any exception, and when used with the test function returns 1:
fooNoException :: Int -> IO Int
fooNoException m = case 3 `div` m of
_ -> return 1
This is because haskell never needs to calculate "3 `div` m" expression (as _ matches everything), so it is never calculated, hence no exception is thrown.