I have a task to generate a list which can contains strings and integers too. How can I solve this problem in Haskell?
That would be [Either String Integer].
Note this is not a list that can contain strings and integers, this is a list of "eithers" where each "either" can contain either a string or an integer (there are two levels of containment). There are various other ways to approximate "a list which can contain strings and integers" but they are not recommended
data StringOrInt
= MyString String
| MyInt Int
deriving (Eq, Show)
x :: [StringOrInt]
x = [MyString "a", MyInt 2]
I'm totally new to functional programming and Haskell, so I am not sure I asked the question properly or if it makes sense, but I decided to try since I haven't found anything helpful. I'm basically trying to implement a function that can return an Int, a String, or a List. I know I can use Either to return one of two types, but I want to return one of three or more. I tried defining a new type, but I got stuck.
data Rets = Int | String | Bool
checkInt :: Rets -> Bool
check x = case x of
Int x -> True
checkInt should return True if given an Int, it is just for testing but I included it anyway.
I'm aware that my question is a mess, so I would be thankful for any kind of explanation. Thanks in advance!
You defined a type with three constructors that each take 0 arguments. So Int x wouldn't be a valid pattern for your type, it would just be Int -> true. Of course this also means that you can't store any values in your type, so it doesn't do what you want it to.
What you want is something like this:
data Rets = IntRet Int | StringRet String | BoolRet Bool
This defines three constructors named IntRet, StringRet and BoolRet, which take an Int, String and Bool respectively. This way you can construct values using IntRet 42, BoolRet True etc. and then pattern match them as IntRet x and so on.
Is it possible to unpack a list into a data type, without specific pattern matching?
for example
data MyType = MyType Int Int Int deriving Show
let l = [1, 2, 3]
func :: [Int] -> MyType
usage would be
λ: func l
λ: Mytype 1 2 3
What I am trying to achieve.*
I have a list of lists which I pulled in from a CSV file. Each of the lists is a list of type variables. I was hoping there would be a fast way of passing those type variables into the type without having to pattern match ten or more variables.
I personally think you should use the pattern matching....
However, you can use the info in this answer to convert a list to a tuple....
How do I convert a list to a tuple in Haskell?
Then you can use the info in this answer to convert that tuple to params for your constructor
Uncurry for n-ary functions
It works, and is sort of intellectually clean, but it is a lot of work to avoid one line of pattern matching.
I'm attempting to simulate a checkers game using haskell. I am given a 4-tuple named, checkersState, that I would like to manipulate with a few different functions. So far, I have a function, oneMove, that receives input from checkerState and should return a tuple of the modified data:
The Input Tuple:
(
3600,
"",
[
"----------",
"------r---",
"----------",
"----------",
"---r-r----",
"------r---",
"---w---w-w",
"----------",
"----------",
"------w---"
],
(
49
,
43
)
)
So far I have something similar to below defining my function but am unsure how to access the individual members within the tuple checkerState. This method will take a time, array of captured pieces, board, and move to make, and return a time, array of captured pieces, and board. Currently, I would like to modify the time (INT) in the tuple depending on the state of the board:
onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
Thanks in advance!
You can use pattern-matching to pull out the elements, do whatever changes need to be made, and pack them back into a tuple. For example, if you wanted to increment the first value, you could:
onemove (a,b,c,d) = (a + 1,b,c,d)
If you find yourself doing this a lot, you might reconsider using a tuple and instead use a data type:
data CheckersState = CheckersState { time :: Int -- field names are just
, steps :: [Char] -- guesses; change them
, board :: [[Char]] -- to something that
, pos :: (Int, Int) -- makes sense
} deriving (Eq, Read, Show)
Then you can update it with a much more convenient syntax:
onemove state = state { time = time state + 1 }
If you want to stick with tuples and you happen to be using lenses, there’s another easy way to update your tuple:
onemove = over _1 (+1)
Or if you’re using lenses and your own data type (with an appropriately-defined accessor like the one provided), you can do something similar:
_time :: Lens' CheckersState Int
_time f state = (\newTime -> state { time = newTime }) <$> f (time state)
onemove = over _time (+1)
So there’s plenty of fancy ways to do it. But the most general way is to use pattern-matching.
As icktoofay is saying, using tuples is a code smell, and records with named components is way better.
Also, using Char (and String) is a code smell. To repair it, define a data type that precisely describes what you expect in a cell of the board, like data Colour = None | Red | Black, but see next item.
And, using Lists is also a code smell. You actually want something like type Board = Data.Map.Map Pos Colour or Data.Map.Map Pos (Maybe Colour') with data Colour' = Red | Black.
Oh, and Int is also a code smell. You could define newtype Row = Row Int ; newtype Col = Col Int ; type Pos = (Row,Col). Possibly deriving Num for the newtypes, but it's not clear, e.g., you don't want to multiply row numbers. Perhaps deriving (Eq,Ord,Enum) is enough, with Enum you get pred and succ.
(Ah - this Pos is using a tuple, thus it`s smelly? Well, no, 2-tuples is allowed, sometimes.)
You use pattern matching to decompose the tuple into variables.
onemove (i, c, board, (x, y)) = <do something> (i, c, board)
However, you should define a separate data structure for the board to make your intention clear. I don't know what the meaning of the first two values. See: http://learnyouahaskell.com/making-our-own-types-and-typeclasses
Record syntax seems extremely convenient compared to having to write your own accessor functions. I've never seen anyone give any guidelines as to when it's best to use record syntax over normal data declaration syntax, so I'll just ask here.
You should use record syntax in two situations:
The type has many fields
The type declaration gives no clue about its intended layout
For instance a Point type can be simply declared as:
data Point = Point Int Int deriving (Show)
It is obvious that the first Int denotes the x coordinate and the second stands for y. But the case with the following type declaration is different (taken from Learn You a Haskell for Great Good):
data Person = Person String String Int Float String String deriving (Show)
The intended type layout is: first name, last name, age, height, phone number, and favorite ice-cream flavor. But this is not evident in the above declaration. Record syntax comes handy here:
data Person = Person { firstName :: String
, lastName :: String
, age :: Int
, height :: Float
, phoneNumber :: String
, flavor :: String
} deriving (Show)
The record syntax made the code more readable, and saved a great deal of typing by automatically defining all the accessor functions for us!
In addition to complex multi-fielded data, newtypes are often defined with record syntax. In either of these cases, there aren't really any downsides to using record syntax, but in the case of sum types, record accessors usually don't make sense. For example:
data Either a b = Left { getLeft :: a } | Right { getRight :: b }
is valid, but the accessor functions are partial – it is an error to write getLeft (Right "banana"). For that reason, such accessors are generally speaking discouraged; something like getLeft :: Either a b -> Maybe a would be more common, and that would have to be defined manually. However, note that accessors can share names:
data Item = Food { description :: String, tastiness :: Integer }
| Wand { description :: String, magic :: Integer }
Now description is total, although tastiness and magic both still aren't.