I'm new to Haskell and want to get the values of the leafs of a self-defined Tree into a record. I started with this.
data MyTree = A Int | B Int MyTree | C Double | D Double MyTree
test = B 1 ( B 1( D 0.02(A 2)))
data MyRecord = MyRecord {A, B :: Int, C :: Double, D :: (Int,Double)}
emptyRecord = MyRecord{a = 0, b = 0, c = 0, d =(0,0)}
Now i started like this:
MyTree2MyRecord :: MyTree -> MyRecord
MyTree2MyRecord(A a1) = emptyRecord{a = a1}
MyTree2MyRecord(B b1 myTree) = emptyRecord {b = b1}
MyTree2MyRecord(C c1) = emptyRecord {c = c1}
MyTree2MyRecord(D d1 myTree) = emptyRecord {d = d1}
where mytree = MyTree2MyRecord -{dont know the recursive call to iterate through the tree and get the values of the leafs}
I understand the simple examples like sum up the leafs of a tree etc, but cant figure out a solution for this problem. I would really appreciate a small hint. Thanks guys
There are some problems with your code:
Function name should start with small case letters. Hence the record data structure should be like this:
data MyRecord = MyRecord {a, b :: Int, c :: Double, d :: (Int,Double)}
And your function name should be like this:
myTree2MyRecord :: MyTree -> MyRecord
Now going through your actual code, you seem to be in almost right path. But in order to find the solution, you have to answer some of these questions:
What exactly does the Int denote in d :: (Int, Double) ?
When you are pattern matching for data constructors like A, B etc., you seem to be assigning the values of the MyTree ADT to the record. Think about the recursive case there. What output do you want for input like this:
myTree2MyRecord (B 1 (B 1 (A 1)))
Your current implementation just discards the value of MyTree in it:
myTree2MyRecord(B b1 myTree) = emptyRecord {b = b1}
Instead of discarding think what should happen to myTree in this case. This will lead to a recursive solution.
And finally, formulate what output do you want for the input which you have given for the question:
test = B 1 ( B 1( D 0.02(A 2)))
Once you answer these question, I think you will refactor the code and solve this problem yourself.
Related
Let us say we have
data D = X Int | Y Int Int | Z String
I wish to have a function getDConst
getDConst :: D -> String
that returns either "X", "Y", or "Z", according to the data constructor used for its input. Is there a generic way to write this without having to do case on every data constructor? (I am ok with solutions relying on Data.Typeable or something similar)
Found the solution myself, but leaving this question to help others:
import Data.Data
data D = X Int | Y Int Int deriving (Data,Typeable)
let result = show $ toConstr (X 3) -- result contains what we wanted
If you don't want to use Typeable, you can also do this with Show.
getDConst :: D -> String
getDConst = head . words . show
Show will not output all the fields, because it is lazy. You can test it runing this code in ghci:
Prelude> data D = D [Int] deriving (Show)
Prelude> getDConst $ D [1..]
"D"
I have a much basic answer to the question without going through imports or whatever. It's Just a simple mere function.
let's say I have the following data. The repetitive Int in the data definition is intentional because I will use the don't care symbol afterwards:
data YES_NO_CANCEL = YES Int | NO Int Int | CANCEL Int Int Int
then you can make a function as :
extractDataType :: YES_NO_CANCEL -> String
extractDataType (YES _) = "YES"
extractDataType (NO _ _) = "NO"
extractDataType (CANCEL _ _ _) = "CANCEL"
I have this code that will return the index of a char in a char array but I want my function to return something like -1 if the value isn't in the array. As it stands the function returns the size of the array if the element isn't in the array. Any ideas on how to change my code in order to apply this feature?
I am trying not to use any fancy functions to do this. I just want simple code without built-in functions.
isPartOf :: [(Char)] -> (Char) -> Int
isPartOf [] a = 0
isPartOf (a:b) c
| a == c = 0
| otherwise = 1 + isPartOf b c
For example:
*Main> isPartOf [('a'),('b'),('c')] ('z')
3
But I want:
*Main> isPartOf [('a'),('b'),('c')] ('z')
-1
Let's try to define such a function, but instead of returning -1 in case of element being not a part of the list, we can return Nothing:
isPartOf :: Eq a => [a] -> a -> Maybe Int
isPartOf [] _ = Nothing
isPartOf (x : xs) a | x == a = Just 0
| otherwise = fmap ((+) 1) (isPartOf xs a)
So, it works like that:
>> isPartOf [('a'),('b'),('c')] ('z')
Nothing
it :: Maybe Int
>> isPartOf [('a'),('b'),('c')] ('c')
Just 2
it :: Maybe Int
After that we can use built-in function fromMaybe to convert the Nothing case to -1:
>> fromMaybe (-1) $ isPartOf [('a'),('b'),('c')] ('c')
2
it :: Int
>> fromMaybe (-1) $ isPartOf [('a'),('b'),('c')] ('z')
-1
it :: Int
In case you're curios if such a function already exist, you can use Hoogle for that, searching the [a] -> a -> Maybe Int function: https://www.haskell.org/hoogle/?hoogle=%5Ba%5D+-%3E+a+-%3E+Maybe+Int
And the first answer will be elemIndex:
>> elemIndex 'c' [('a'),('b'),('c')]
Just 2
it :: Maybe Int
>> elemIndex 'z' [('a'),('b'),('c')]
Nothing
it :: Maybe Int
Hope this helps.
The smallest change to achieve this is
isPartOf :: [Char] -> Char -> Int
isPartOf [] a = (-1) -- was: 0
isPartOf (a:b) c
| a == c = 0
| otherwise = 1 + -- was: isPartOf b c
if (isPartOf b c) < 0 then (-2) else (isPartOf b c)
This is terrible computationally though. It recalculates the same value twice; what's worse is that the calculation is done with the recursive call and so the recursive call will be done twice and the time complexity overall will change from linear to exponential!
Let's not do that. But also, what's so special about Char? There's lots of stuff special about the Char but none are used here, except the comparison, (==).
The types the values of which can be compared by equality are known as those belonging to the Eq (for "equality") type class: Eq a => a. a is a type variable capable of assuming any type whatsoever; but here it is constrained to be such that ... yes, belongs to the Eq type class.
And so we write
isPartOf :: Eq a => [a] -> a -> Int
isPartOf [] a = (-1)
isPartOf (a:b) c
| a == c = 0
| otherwise = let d = isPartOf b c in
1 + if d < 0 then (-2) else d
That (-2) looks terribly ad-hoc! A more compact and idiomatic version using guards will also allow us to address this:
isPartOf :: Eq a => [a] -> a -> Int
isPartOf [] a = (-1)
isPartOf (a:b) c
| a == c = 0
| d < 0 = d
| otherwise = 1 + d
where
d = isPartOf b c
Yes, we can define d in the where clause, and use it in our guards, as well as in the body of each clause. Thanks to laziness it won't even be calculated once if its value wasn't needed, like in the first clause.
Now this code is passable.
The conditional passing and transformation is captured by the Maybe data type's Functor interface / instance:
fmap f Nothing = Nothing -- is not changed
fmap f (Just x) = Just (f x) -- is changed
which is what the other answer here is using. But it could be seen as "fancy" when we only start learning Haskell.
When you've written more functions like that, and become "fed up" with repeating the same pattern manually over and over, you'll come to appreciate it and will want to use it. But only then.
Yet another concern is that our code calculates its result on the way back from the recursion's base case.
But it could instead calculate it on the way forward, towards it, so it can return it immediately when the matching character is found. And if the end of list is found, discard the result calculated so far, and return (-1) instead. This is the approach taken by the second answer.
Though creating an additional function litters the global name space. It is usual to do this by defining it internally, in the so called "worker/wrapper" transformation:
isPartOf :: Eq a => [a] -> a -> Int
isPartOf xs c = go xs 0
where
go [] i = (-1)
go (a:b) i
| a == c = i
| otherwise = -- go b (1 + i)
go b $! (1 + i)
Additional boon is that we don't need to pass around the unchanged value c -- it is available in the outer scope, from the point of view of the internal "worker" function go, "wrapped" by and accessible only to our function, isPartOf.
$! is a special call operator which ensures that its argument value is calculated right away, and not delayed. This eliminates an unwanted (in this case) laziness and improves the code efficiency even more.
But from the point of view of overall cleanliness of the design it is better to return the index i wrapped in a Maybe (i.e. Just i or Nothing) instead of using a "special" value which is not so special after all -- it is still an Int.
It is good to have types reflect our intentions, and Maybe Int expresses it clearly and cleanly, so we don't have to remember which of the values are special and which regular, so that that knowledge is not external to our program text, but inherent to it.
It is a small and easy change, combining the best parts from the two previous variants:
isPartOf :: Eq a => [a] -> a -> Maybe Int
isPartOf .....
.......
....... Nothing .....
.......
....... Just i .....
.......
(none of the code was tested. if there are errors, you're invited to find them and correct them, and validate it by testing).
You can achieve it easily if you just pass current element idx to the next recursion:
isPartOf :: [Char] -> Char -> Int
isPartOf lst c = isPartOf' lst c 0
isPartOf' :: [Char] -> Char -> Int -> Int
isPartOf' [] a _ = -1
isPartOf' (a:b) c idx
| a == c = idx
| otherwise = isPartOf' b c (idx + 1)
You are using your function as an accumulator. This is cool except the additions with negative one. An accumulator cannot switch from accumulating to providing a negative 1. You want two different things from your function accumulator. You can use a counter for one thing then if the count becomes unnecessary because no match is found and a negative 1 is issued and nothing is lost. The count would be yet another parameter. ugh. You can use Maybe but that complicates. Two functions, like above is simpler. Here are two functions. The first is yours but the accumulator is not additive it's concatenative.
cIn (x:xs) c | x == c = [1]
| null xs = [-1]
| otherwise = 1:cIn xs c
Cin ['a','b','c'] 'c'
[1,1,1]
cIn ['a','b','c'] 'x'
[1,1,-1]
So the second function is
f ls = if last ls == 1 then sum ls else -1
It will
f $ Cin ['a','b','c'] 'c'
3
and
f $ Cin ['a','b','c'] 'x'
-1
You can zero the index base by changing [1] to [0]
The following data structure can be tested with the Tasty-SmallCheck related code that follows. There is a relation that has to hold with the constructor ShB: the second and the third positive integers should be at most as large as the first one.
data Shape = ShA Int Int Bool
| ShB Int Int Int Bool Bool
deriving (Show,Read,Eq)
The constructor ShA should have positive Int's but otherwise there is no relation between the parameters.
auxShA :: (Positive Int, Positive Int, Bool) -> Shape
auxShA (i,j,b) = ShA (fromIntegral i) (fromIntegral j) b
auxShB :: (Positive Int, Positive Int, Positive Int) -> Bool -> Bool -> Shape
auxShB (a1,a2,a3) = ShB i u d
where
(i,u,d) = auxTriplet (a1,a2,a3)
auxTriplet :: (Positive Int, Positive Int, Positive Int) -> (Int,Int,Int)
auxTriplet (a,b,c)
| a >= b && a >= c = (fromIntegral a, fromIntegral b, fromIntegral c)
| b >= a && b >= c = (fromIntegral b, fromIntegral a, fromIntegral c)
| otherwise = (fromIntegral c, fromIntegral a, fromIntegral b)
consB :: (Serial m a1, Serial m a2, Serial m a3, Serial m b, Serial m c) =>
((a1,a2,a3) -> b -> c -> e) -> Series m e
consB f = decDepth $
f <$> series
<~> series
<~> series
instance Monad m => Serial m Shape where
series = cons1 auxShA \/ consB auxShB
The generated cases are otherwise ok but there are duplicates that can be seen e.g. with
list 4 series :: [Shape]
The question is, how to generate the test cases with SmallCheck (tasty) when the following holds?
there are properties that has to hold, e.g. the first parameter has to Positive
what if the first parameter should be larger than 10::Int?
And continuing, what if the second parameter should between the first - 5 and the first, and the third should be between the second - 5 and the second?
Or, how to generate test cases that dynamically can depend on the previous generated values?
First thought was to write constructors to Shape that check that inputs are valid (e.g. the bullet points above), but the problem of duplicate test case generation would remain with that approach.
The above code uses similar solution as in
SmallCheck invariant -answer.
I'm still trying to grasp an intuition of pullbacks (from category theory), limits, and universal properties, and I'm not quite catching their usefulness, so maybe you could help shed some insight on that as well as verifying my trivial example?
The following is intentionally verbose, the pullback should be (p, p1, p2), and (q, q1, q2) is one example of a non-universal object to "test" the pullback against to see if things commute properly.
-- MY DIAGRAM, A -> B <- C
type A = Int
type C = Bool
type B = (A, C)
f :: A -> B
f x = (x, True)
g :: C -> B
g x = (1, x)
-- PULLBACK, (p, p1, p2)
type PL = Int
type PR = Bool
type P = (PL, PR)
p = (1, True) :: P
p1 = fst
p2 = snd
-- (g . p2) p == (f . p1) p
-- TEST CASE
type QL = Int
type QR = Bool
type Q = (QL, QR)
q = (152, False) :: Q
q1 :: Q -> A
q1 = ((+) 1) . fst
q2 :: Q -> C
q2 = ((||) True) . snd
u :: Q -> P
u (_, _) = (1, True)
-- (p2 . u == q2) && (p1 . u = q1)
I was just trying to come up with an example that fit the definition, but it doesn't seem particularly useful. When would I "look for" a pull back, or use one?
I'm not sure Haskell functions are the best context
in which to talk about pull-backs.
The pull-back of A -> B and C -> B can be identified with a subset of A x C,
and subset relationships are not directly expressible in Haskell's
type system. In your specific example the pull-back would be
the single element (1, True) because x = 1 and b = True are
the only values for which f(x) = g(b).
Some good "practical" examples of pull-backs may be found
starting on page 41 of Category Theory for Scientists
by David I. Spivak.
Relational joins are the archetypal example of pull-backs
which occur in computer science. The query:
SELECT ...
FROM A, B
WHERE A.x = B.y
selects pairs of rows (a,b) where a is a row from table A
and b is a row from table B and where some function of a
equals some other function of b. In this case the functions
being pulled back are f(a) = a.x and g(b) = b.y.
Another interesting example of a pullback is type unification in type inference. You get type constraints from several places where a variable is used, and you want to find the tightest unifying constraint. I mention this example in my blog.
Let us say we have
data D = X Int | Y Int Int | Z String
I wish to have a function getDConst
getDConst :: D -> String
that returns either "X", "Y", or "Z", according to the data constructor used for its input. Is there a generic way to write this without having to do case on every data constructor? (I am ok with solutions relying on Data.Typeable or something similar)
Found the solution myself, but leaving this question to help others:
import Data.Data
data D = X Int | Y Int Int deriving (Data,Typeable)
let result = show $ toConstr (X 3) -- result contains what we wanted
If you don't want to use Typeable, you can also do this with Show.
getDConst :: D -> String
getDConst = head . words . show
Show will not output all the fields, because it is lazy. You can test it runing this code in ghci:
Prelude> data D = D [Int] deriving (Show)
Prelude> getDConst $ D [1..]
"D"
I have a much basic answer to the question without going through imports or whatever. It's Just a simple mere function.
let's say I have the following data. The repetitive Int in the data definition is intentional because I will use the don't care symbol afterwards:
data YES_NO_CANCEL = YES Int | NO Int Int | CANCEL Int Int Int
then you can make a function as :
extractDataType :: YES_NO_CANCEL -> String
extractDataType (YES _) = "YES"
extractDataType (NO _ _) = "NO"
extractDataType (CANCEL _ _ _) = "CANCEL"