I have a function of type foo :: a -> a -> Either String TypeConstructor
foo can return both throwError String and something of TypeConstructor.
I would like to do something like fmap. I mean that I would like to case (foo x y z) of ... where ... means different values (it depends on used constructor value in foo).
Is there exista any way to do it ?
A basic way could be to pattern match everything
case foo x y of
Left string -> ...
Right (Cons1 z w) -> ...
Right (Cons2 a b c) -> ...
Right Cons3 -> ...
where Cons1, ... are the value constructors of TypeConstructor.
You can't directly write
case (foo x y) of ...
and then pattern match on the type constructors of TypeConstructor since foo x y does not have the correct type (it is Either String TypeConstructor).
However, you can define a function which pattern matches on the type constructors of TypeConstructor and then fmap this over the result of foo x y as shown below.
import Control.Monad.Except (throwError)
data Type = Int Int
| Str String
deriving (Show)
foo :: Int -> String -> Either String Type
foo n s =
if n == 0
then throwError "Zero"
else return (Str s)
bar x y = fmap f (foo x y)
where
f a = case a of
Int n -> Int (n + x)
Str s -> Str (s ++ y)
Related
I know I can use pattern matching for function parameters like this:
fn :: (Integral a) => (a,a) -> (a, a)
fn (x,y) = (y,x)
But how can I match the return value? I would expect something like this:
g :: (Integral a) => a -> a
g z = do
(x, y) = fn (z, z + 5)
x `mod` y
This results in a syntax error. Is there a way to match return values? Basically, I want to split the returned tuple into two variables.
The do is used a syntactical sugar for monads. Your function is however not a monad.
What you can do is use a let-clause, like:
g :: (Integral a) => a -> a
g z = let (x,y) = fn (z,(z+5)) in x `mod` y
Or a where-clause:
g :: (Integral a) => a -> a
g z = x `mod` y
where (x,y) = fn (z,(z+5))
You can also define a pattern in a lambda-expression, like:
g :: (Integral a) => a -> a
g z = (\(x,y) -> x `mod` y) $ fn (z,(z+5))
Along these lines, you can also define a helper function that does the pattern matching, like:
g :: (Integral a) => a -> a
g z = h $ fn (z,(z+5))
where h (x,y) = x `mod` y
This can be useful if there are several patterns that need to be handled differently (like the Nothing and Just x for the Maybe a type).
Say for instance that you defined a function:
foo :: Int -> Int -> Maybe Int
foo x y | x > y = Just x
| otherwise = Nothing
than you can define bar with a helper function qux to handle the output of foo, like:
bar :: Int -> Int -> Int
bar x y = qux $ foo x y
where qux Nothing = y
qux (Just z) = z
Finally in the case of 2-tuples, you can decide not to use pattern matching, but use fst :: (a,b) -> a and snd :: (a,b) -> b, like for instance:
g :: (Integral a) => a -> a
g z = let t = fn (z,(z+5)) in ( fst t) `mod` (snd t)
But this is less elegant since here one has to start thinking about what fst and snd do, and furtermore if not optimized, it can result in additional computation overhead.
Which one to pick depends of course on the context and a bit on personal taste. Since here the pattern is the only one, I would pick the let or where pattern, but like the French say: "Les goƻts et les couleurs ne se discutent pas.".
My personal preference in the general case, is to use a case .. of expression. For instance, if f :: Int -> Maybe Int, we can write
g :: Int -> Int
g x = case f x of
Nothing -> 5
Just y -> x+y
For types with only one constructor, like tuples, then let .. in can also be used:
h a = let (x, y) = foo a in ...
Remember, however, that case is strict while let is lazy. E.g.
case undefined of (x,y) -> 5
raises an error. Instead
let (x, y) = undefined in 5
evaluates to 5. So, they are not completely equivalent. They became such when using irrefutable patterns, or matching against a newtype constructor.
I'm experimenting with Haskell and I'm wondering why I couldn't match against a Just containing a pair. I have little experience with this language and I'm completely lost.
f :: Int -> Maybe (Int, [Int])
f 100 = Nothing
f x = Just (x,[x])
g :: Int -> Maybe Int
g x
| u==Nothing = Nothing
| u==(Just (r,s)) = Just r
where
u=f x
So what is wrong with this code. GHC says that r and s are not in scope.
If you want to pattern match in a guard, you have to use a pattern guard:
g :: Int -> Maybe Int
g x
| Just (r,_) <- u = Just r
| otherwise = Nothing
where
u = f x
After all, (==) is a regular function, you need values on both sides to use it. Since r and s aren't known in u == Just (r,s), the compiler gives you your error message.
By the way, taking a Maybe and return Nothing if the value was Nothing or Just (h x) for a function h and Just x is so common, it forms a pattern: fmap. You can write
g :: Int -> Maybe Int
g x = fmap fst (f x)
Because the guard expression can't do pattern matching.
Guard expression is just like a boolean expression, it can't do binding. It just uses the binding before |, in this case x.
So working solution will be like this.
g :: Int -> Maybe Int
g x = case f x of
Nothing -> Nothing
Just (r,_) -> Just r
You can use case expressions
g :: Int -> Maybe Int
g x =
case f x of
Nothing -> Nothing
Just (r,s) -> Just r
I have a list of elements:
data Foo = A Int | B Int | C Int
myList :: [Foo]
myList = [A 1, B 2, C 3]
I want a function that gets the value of a specific constructor, if existing:
-- returns value of the first A constructor, if exists:
getA :: [Foo] -> Maybe Int
-- returns value of the first B constructor, if exists:
getB :: [Foo] -> Maybe Int
Any elegant solution?
And what about a getX function, capable of getting the value of any specified constructor in the list?
This will work
getA theList = listToMaybe [x | A x <- theList]
getB theList = listToMaybe [x | B x <- theList]
You will need to import Data.Maybe.
Generalizing this would be possible, but tricky.... What type would you even want this function to have? ([a]->somethingToRepresentAConstructor->Int).
And what about a getX function, capable of getting the value of any specified constructor in the list?
Regarding the generalization, the somethingToRepresentAConstructor could be a String?
You can generalize a bit more and get
firstJust :: (a -> Maybe b) -> [a] -> Maybe b
firstJust f xs = case filter isJust (map f xs) of
x : _ -> x
[] -> Nothing
getA = firstJust f
where f (A x) = Just x
f _ = Nothing
getB = firstJust f
where f (B x) = Just x
f _ = Nothing
Say I have
x = Just 2
Is there a way (preferrably a builtin mechanism/function) to use x in a single statement such that if it is a Just, then the 2 is automatically unwrapped and used, and if it is a Nothing, an exception is raised?
That is,
(f x) + 2 == 4 if x == Just 2, and raises an exception if x == Nothing.
Data.Maybe.fromJust has been mentioned by other answers already:
fromJust :: Maybe a -> a
fromJust Nothing = error "Maybe.fromJust: Nothing"
fromJust (Just x) = x
There's also maybe (found in both Prelude and Data.Maybe):
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing = n
maybe _ f (Just x) = f x
fromJust can be written using maybe:
fromJust = maybe (error "Maybe.fromJust: Nothing") id
As you can see, maybe allows you flexibility in handling both cases without requiring pattern matching:
\x -> maybe 0 (+ 2) x -- Nothing -> 0, Just 2 -> 4
Similarly, Prelude and Data.Either have either :: (a -> c) -> (b -> c) -> Either a b -> c:
\x -> either (subtract 1) (* 2) x -- Left 5 -> 4, Right 3 -> 6
If you define a data type
data MyDataType
= TypeA { foo :: Int, bar :: String }
| TypeB { foo :: Int, baz :: () }
| TypeC { bar :: String, baz :: () }
like this, you end up with partial functions for accessors.
foo :: MyDataType -> Int
bar :: MyDataType -> String
baz :: MyDataType -> ()
They're called partial functions, as opposed to total functions, because they only return results for a subset of their inputs.
foo (TypeA { foo = 15, bar = "hello!" }) -- 15
bar (TypeB { foo = 12345679, baz = () }) -- error
For this particular case, fromJust. In general
let Just k = x in f k + 2 == 4
This trick works with any datatype constructor and is very commonly used with (:) for nonempty lists.
fromJust should do what you want.
If SomeType is defined as:
data SomeType = X {myBool :: Bool}
| Y {myString :: String}
| Z {myString :: String}
and I will update an arbitrary X, dependent of his type as follows:
changeST :: SomeType -> SomeType
changeST (X b) = (X True)
changeST (Y s) = (Y "newString")
changeST (Z s) = (Z "newString")
The third and the fourth line do the very same, they update the string in the given type.
Is there any way replace these two lines by a single one, eg. by assigning the type to a variable?
Not by assigning the type to a variable, but by doing field replacement:
changeST :: SomeType -> SomeType
changeST (X b) = (X True)
changeST st = st { myString = "newString" }
This returns the same st as its argument, but with the value of the myString field replaced. It's one of the nice features of fields that you can do this without caring which data constructor it is, as long as it's one of the data constructors that uses myString.
You can use Scrap-Your-Boilerplate for this.
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Generics
data SomeType
= X { myBool :: Bool }
| Y { myString :: String }
| Z { myString :: String }
deriving (Data, Typeable)
changeST :: SomeType -> SomeType
changeST = everywhere (mkT (const True)) . everywhere (mkT (const "newString"))
This changeST changes every internal String in your structure to "newString" and every Bool to True.
I prefer Dan's solution, but pattern guards in GHC (standard in Haskell 2010) are a neat alternative to Michael's proposal:
{-# LANGUAGE PatternGuards #-}
changeST :: SomeType -> SomeType
changeST x | X _ <- x = X True
| Y _ <- x = Y newString
| Z _ <- x = Z newString
where newString = "newString"
Your three definitions of changeST are separate from each other, so the short answer is "no". There are, however, at least two ways you can do this.
Pattern match both the Y and Z constructors at once:
You can combine the 2nd and 3rd definition by making your pattern matching more general:
changeST x = x { myString = "newString"}
This creates a new version of x, whether it be a Y or a Z, replacing the string member. You have to be careful when doing this, though. If you later rename the string field of Z, for example, you will get runtime pattern match failures when calling changeST with a Z argument.
Use a case expression:
If you combine your three definitions into one, you can share data between them.
changeST :: SomeType -> SomeType
changeST x = case x of
X _ -> X True
Y _ -> Y newString
Z _ -> Z newString
where
newString = "newString"