First post here, please go easy on me. Found several threads with similar issues, none of those applied directly or if one did, the execution was far enough over my head.
If i have code p=['1','2','3','4'] that stores digits as characters in p, how do i create a list q that can equal [1,2,3,4]?
I've been trying all sorts of things, mostly arriving at my q being out of scope or any function i try to convert Char -> Int lacking accompanying binding.
I seem to find indication everywhere that there is such a thing as digitToInt, where digitToInt '1' should yield an output of 1 but i apparently lack bindings, even with the exact input from this page:
http://zvon.org/other/haskell/Outputchar/digitToInt_f.html
At this point reading more things i am just becoming more confused. Please help with either a viable solution that might show me where i'm messing up or with an explanation why this digitToInt :: Char -> Int seems to not work for me in the slightest.
Thank you.
digitToInt is something that already exists. It used to live in the Char module but now it lives in Data.Char, so we have to import Data.Char to use it.
Prelude> import Data.Char
Prelude Data.Char> digitToInt '1'
1
You can use digitToInt on every element of a list with map digitToInt. map :: (a->b) -> [a] -> [b] applies a function (a->b) to each element of a list of as, [a] to get a list of bs, [b].
Prelude Data.Char> map digitToInt ['1', '2', '3', '4']
[1,2,3,4]
Lacks an accompanying binding
You don't need to define digitToInt or other imports by writing it's type signature digitToInt :: Char -> Int. A signature written without a binding like that
alwaysSeven :: Char -> Int
will give the following error.
The type signature for `alwaysSeven' lacks an accompanying binding
You only provide a type signature when it comes right before a declaration.
alwaysSeven :: Char -> Int
alwaysSeven x = 7
Without importing anything you can also use a very simply trick, and push ((:[])) the character in an empty list (making a singleton list) before reading the value:
map (read . (:[])) "1234"
This will need the context of the type of the list to be deducible, but it will work for any type you want without modifications. Otherwise you'll need to specify the type yourself:
(map (read . (:[])) "1234") :: [Int]
-- [1,2,3,4]
(map (read . (:[])) "1234") :: [Double]
-- [1.0,2.0,3.0,4.0]
Here are the type signatures of chunksOf and splitPlaces from Data.List.Split:
chunksOf :: Int -> [e] -> [[e]]
splitPlaces :: Integral a => [a] -> [e] -> [[e]]
Why do some functions (like chunksOf) use Int while others (like splitPlaces) use the more generic Integral a?
In this answer, I try to look at the historical reasons for the inconsistent interface. Summary: It seems that Brent made some functions more generic on the fly to help formulating QuickCheck properties.
Why is splitPlaces generic?
It looks as if Brent generalized the type of splitPlaces to make it easier to introduce QuickCheck properties for that function. The QuickCheck properties use newtype wrappers to control test case generation, and with the Integral a constraint, splitPlaces could look through this newtype wrapper for the arithmetic operations. See also:
The patch
that generalizes the type of splitPlaces and introduces the QuickCheck properties.
The QuickCheck documentation about these newtype wrappers.
However, here is one of the properties about splitPlaces:
prop_splitPlaces_preserve :: [NonNegative Integer] -> [Elt] -> Bool
prop_splitPlaces_preserve ps l = concat (splitPlaces ps' l) == genericTake (sum ps') l
where ps' = map unNN ps
Note that QuickCheck automatically generates the list ps which is converted by map unNN ps before being passed to splitPlaces. The unNN function removes the NonNegative wrapper, so splitPlaces does not have to deal with the NonNegative wrapper itself. However, it receives an argument of type [Integer] instead of [Int], so it still needs to be generic in the numeric type.
What's the point of using [NonNegative Integer] instead of [NonNegative Int]?
I suspect that the property is false for [Int] because of arithmetic overflows when computing the sum. The property might even be falsifiable by QuickCheck because the Arbitrary [NonNegative Integer] instance will ultimately delegate to arbitrarySizedBoundedIntegral which can generate very large values.
I guess that using [NonNegative Integer] instead circumvents this problem in two ways:
With Integer, no overflows can occur.
The Arbitrary Integer instance delegates to arbitrarySizedIntegral which only generates small values.
So I guess that the reason for allowing arbitrary Integral types is that the QuickCheck property would fail for Int but succeeds for Integer.
Why is chunksOf not generic?
The properties for chunksOf use pattern matching to remove the newtype wrappers. See also:
The patch that introduces properties for splitEvery.
The patch that renames splitEvery to chunksOf.
Here is one of the properties about chunksOf:
prop_chunksOf_all_n :: Positive Int -> NonEmptyList Elt -> Bool
prop_chunksOf_all_n (Positive n) (NonEmpty l) = all ((==n) . length) (init $ chunksOf n l)
Note that this property matches on the arguments that are automatically generated by QuickCheck and passes them to chunksOf without the newtype wrapper. For the arguments necessary for testing chunksOf, this is easy to do, because the numbers are not nested in other types. Compare with prop_splitPlaces_preserve above, where converting [NonNegative Integer] to [Integer] or [Int] requires something more complicated than just pattern matching.
The difference between Arbitrary Int and Arbitrary Integer doesn't matter here, because the property does not involve any operations that can trigger an arithmetic overflow.
Consider this:
ruleset = [rule0, rule1, rule2, rule3, rule4, rule5]
where rule0, rule1, etc. are boolean functions that take one argument. What is the cleanest way to find if all elements of a particular list satisfy all the rules in the ruleset?
Obviously, a loop would work, but Haskell folks always seem to have clever one-liners for these types of problems.
The all function seems appropriate (eg. all (== check_one_element) ruleset) or nested maps. Also, map ($ anElement) ruleset is roughly what I want, but for all elements.
I'm a novice at Haskell and the many ways one could approach this problem are overwhelming.
If you require all the functions to be true for each argument, then it's just
and (ruleset <*> list)
(You'll need to import Control.Applicative to use <*>.)
Explanation:
When <*> is given a pair of lists, it applies each function from the list on the left to each argument from the list on the right, and gives back a list containing all the results.
A one-liner:
import Control.Monad.Reader
-- sample data
rulesetL = [ (== 1), (>= 2), (<= 3) ]
list = [1..10]
result = and $ concatMap (sequence rulesetL) list
(The type we're working on here is Integer, but it could be anything else.)
Let me explain what's happening: rulesetL is of type [Integer -> Bool]. By realizing that (->) e is a monad, we can use
sequence :: Monad m => [m a] -> m [a]
which in our case will get specialized to type [Integer -> Bool] -> (Integer -> [Bool]). So
sequence rulesetL :: Integer -> [Bool]
will pass a value to all the rules in the list. Next, we use concatMap to apply this function to list and collect all results into a single list. Finally, calling
and :: [Bool] -> Bool
will check that all combinations returned True.
Edit: Check out dave4420's answer, it's nicer and more concise. Mine answer could help if you'd need to combine rules and apply them later on some lists. In particular
liftM and . sequence :: [a -> Bool] -> (a -> Bool)
combines several rules into one. You can also extend it to other similar combinators like using or etc. Realizing that rules are values of (->) a monad can give you other useful combinators, such as:
andRules = liftM2 (&&) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
orRules = liftM2 (||) :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
notRule = liftM not :: (a -> Bool) -> (a -> Bool)
-- or just (not .)
etc. (don't forget to import Control.Monad.Reader).
An easier-to-understand version (without using Control.Applicative):
satisfyAll elems ruleset = and $ map (\x -> all ($ x) ruleset) elems
Personally, I like this way of writing the function, as the only combinator it uses explicitly is and:
allOkay ruleset items = and [rule item | rule <- ruleset, item <- items]
just started learning haskell - love it after a week. At the moment going through the monads pain, not there yet but hopefully it will click.
I am trying to put together a function similar to pythons walk() but simpler.
Given a path I want to generate list of tuples. A tuple for each sub directory (lets just assume that there will be only directories). The tuple would contain path of the directory as its first element and list of files the directory contains as the second element.
I don't know if I explained it correctly but here is the code:
walkDir :: String -> IO [IO (FilePath, [FilePath])]
walkDir path = do
dir <- getDirectoryContents path
let nd = [x | x <- dir, notElem x [".",".."]]
return (map getcont nd)
where
getcont path = do
cont <- getDirectoryContents path
return (path,cont)
My concern is IO inside IO and how to deal with it?? Is it possible to cancel them out?
Is it possible to unwrap at least the internal IO? Is this kind of return normal?
I can not even print this kind of return. Do I have to create an instance of show for this to be printed correctly?
There most likely exist a similar function in some haskell library but this is for educational purpose. I want to learn. So any suggestions welcome.
Thank you very much.
Check out Control.Monad for mapM.
Then this
return (map getcont nd)
becomes
mapM getcont nd
Let's look at the types.
map :: (a -> b) -> [a] -> [b]
getCont :: FilePath -> IO (FilePath, [FilePath])
nd :: [FilePath]
map getCont nd :: [IO (FilePath, FilePath)]
Now, at this point, the structure looks inside-out. We have [IO a] but we want IO [a]. Stop! Hoogle time. Generalizing for any ol' monad, we hoogle [m a] -> m [a]. Lo and behold, sequence has that precise type signature. So instead of return :: a -> m a you should use sequence :: [m a] -> m [a], like this:
sequence (map getCont nd)
Then you'll be all set. Notice that this is essentially identical to Kurt S's solution, because
mapM f xs = sequence (map f xs)
How can I best convert a list to a tuple in Haskell:
[1,2,3,4,5,6] -> (1,2,3,4,5,6)
In a general way, you can't. Each size of tuple is a distinct type, whereas lists of any length are a single type. Thus, there's no good way to write a function that takes a list and returns a tuple of the same length--it wouldn't have a well-defined return type.
For instance, you could have functions like:
tuplify2 :: [a] -> (a,a)
tuplify2 [x,y] = (x,y)
tuplify3 :: [a] -> (a,a,a)
tuplify3 [x,y,z] = (x,y,z)
...but not one that does the job of both.
You can write a generic version using various kinds of meta-programming, but you'd rarely want to.
Note that the same problem applies to other things, such as writing class instances for various tuples--take a look at the source code for Data.Tuple from the standard libraries!
Template Haskell is as close as you can get due to type checking if you want to extract a variable number of elements, since (a,b) and (a,b,c) have different types.
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
tuple :: Int -> ExpQ
tuple n = do
ns <- replicateM n (newName "x")
lamE [foldr (\x y -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns)
Then:
$(tuple 6) [1,2,3,4,5,6] == (1,2,3,4,5,6)
$(tuple 3) "abc" == ('a','b','c')
But in general, if you need this answer, then you're asking the wrong question somewhere.
If you just want flat random access, perhaps the better option would be to use an Array.
If feel like I am about to advise you to point a gun at your foot and trust you not to shoot.
> list2Tuple lst = read $ "(" ++ (init.tail.show) lst ++ ")"
> list2Tuple [1,2,3] :: (Int, Int, Int)
(1,2,3)
> list2Tuple [1,2,3,4] :: (Int, Int, Int, Int)
(1,2,3,4)
This will work up to the what ever length of tuple Show and Read are defined for.
Tuples and lists are very different things. About the best you can do is to manually write a conversion function:
toTuple :: [a] -> (a,a,a,a,a,a)
toTuple [a,b,c,d,e,f] = (a,b,c,d,e,f)
Notice how different the types are: the single variable of the list expands to six variables for the tuple. So you'll need one function for each size of tuple.
I find it difficult to make cogent explanations of Template Haskell manipulations, but here is a demonstration:
> :m +Language.Haskell.TH
> :set -XTemplateHaskell
> runQ [| [1,2,3,4,5,6] |] >>= putStrLn . pprint
[1, 2, 3, 4, 5, 6]
> runQ [| [1,2,3,4,5,6] |] >>= \ (ListE exps) -> putStrLn (pprint (TupE exps))
(1, 2, 3, 4, 5, 6)
I don't think it's possible to do this in Haskell, for a list of arbitrary length not known at compile time. Template Haskell can't do it because it operates only at compile time. I ran into a case where I needed to do precisely this, and I had to work around it. A database library expects different-length tuples for query arguments, but I have an arbitrary-length list. So I have to skirt around the library interface. It would be nice if it could take a list.
Basically the issue is that different-length tuples are different types. But the Haskell compiler has to know at compile type what types might exist at runtime. Converting an arbitrary-length list into a tuple at run time could create some type it didn't know about at compile time.
You can in fact do better than manually writing one function per tuple-size if you use quasi-quotation as explained here. However, I would wonder about code where you expect to use this generically.
When dealing with command line arguments you can use getArgs, that function will give you a list with strings:
getArgs :: IO [String]
Link: https://hackage.haskell.org/package/base-4.16.0.0/docs/System-Environment.html#v:getArgs
When I work with command line arguments I prefer to work with tuples instead of a list, so I convert the list to a tuple. See below:
import System.Environment
main = do
args <- getArgs
let (a:b:c) = args
print a
Calling the program (in PowerShell):
PS C:\Haskell> runghc convertListToTuple goodday to you
"goodday"