How to get custom data type member? - haskell

This is what I have tried so far. I wanted to make a type Info with a String and two Ints. Now I want to access the String for a given instance of that type. I have read Accessing members of a custom data type in Haskell.
I did not expect this to work but couldn't search for what I'm looking for:
Prelude> data Info = Info String Int Int
Prelude> aylmao = Info "aylmao" 2 3
Prelude> aylmao . String
<interactive>:4:1: error:
• Couldn't match expected type ‘b0 -> c’ with actual type ‘Info’
• In the first argument of ‘(.)’, namely ‘aylmao’
In the expression: aylmao . String
In an equation for ‘it’: it = aylmao . String
• Relevant bindings include
it :: a -> c (bound at <interactive>:4:1)
<interactive>:4:10: error:
Data constructor not in scope: String :: a -> b0
Prelude>
I want to be able to access any anonymous member of my type, how can I do this?

How to get custom data type member?
data Info = Info String Int Int
As Willem Van Onsem said, you can write a function that does this:
infoString :: Info -> String
infoString (Info s _ _) = s
Or you can use record syntax to name your data type fields:
data Info = Info { infoString :: String
, infoInt1 :: Int
, infoInt2 :: Int
}
and use the automatically generated infoString :: Info -> String as a function.
Preferrably, come up with better names for those fields.

Related

String replace using map compilation error

I am new to Haskell, and trying to implement the code from here to replace strings using a map. I am getting an error message during compilation that says
* Expecting one more argument to `StringMap'
Expected a type, but `StringMap' has kind `* -> *'
* In the type signature:
stringMapReplace :: (Show stringMap) => StringMap -> String -> String
I have tried searching, but the only answer I can find for the error is that I'm not clarifying what type StringMap is. However, I thought that is what Show stringMap was doing.
import Data.Map
import Data.Strings
type StringMap stringMap = [(String, String)]
myStringMap =
[
("org1", "rep1"),
("org2", "rep2")
]
stringMapReplace :: (Show stringMap) => StringMap -> String -> String
stringMapReplace [] s = s
stringMapReplace (m:ms) s = strReplace ms (replace (fst m) (snd m) s)
main :: IO ()
main = do
putStrLn "Enter some text:"
putStrLn =<< stringMapReplace myStringMap <$> toUpper getLine
Note: strReplace comes from Data.Strings
I don't know if there is anything else wrong with the code, as the compiler is only giving the error above right now. If you notice anything else right off, please feel free to mention (or leave it for me to debug later as practice).
You defined the type synonym StringMap to take an (unused) type parameter stringMap. Type synonyms, as opposed to newtype, data, and GADT declarations, must always be fully applied. Thus every occurrence of StringMap must be have a parameter supplied, like forall a . StringMap a, StringMap Int, etc. In the signature of stringMapReplace, you do not give StringMap a parameter, hence the error.
Two options:
Change StringMap to type StringMap = [(String, String)], because it doesn't need a parameter.
Give StringMap a parameter in the signature of stringMapReplace. What parameter, you ask? Any one, because it is ignored. For example, the following should work:
stringMapReplace :: StringMap String -> String -> String

read::Int not working in Haskell in example

Here is the problem. It looks simple yet
main = do
s <- getContents
let list = map (read::Int) (words s)
print list
Couldn't match expected type `Int' with actual type `String -> a0'
Probable cause: `read' is applied to too few arguments
In the first argument of `map', namely `(read :: Int)'
In the expression: map (read :: Int) (words s)
The problem was that I thought :: is like casting and I have to put the return type. The solution was to add full wanted |function signature instread.
read is a function (of type Read a => String -> a), so it can't have type Int. You could do read :: String -> Int, or you could put a type signature on list rather than read, so you get:
let list :: [Int]
list = map read (words s)

Text.Tabular.Table type errors - what is the type system asking from me?

I have the following code, using this tabulation library:
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}
import ClassyPrelude
import qualified Text.Tabular as T
data Category = Age | Gender | Usual | Years
deriving (Show, Read, Eq, Enum, Bounded)
tabulate :: Text -> [[Int]] -> T.Table (T.Header Int) (T.Header Text) Int
tabulate lbl tab = T.Table (T.Group T.NoLine (map T.Header leftcoll)) (T.Group T.DoubleLine [T.Header lbl, T.Header "All", T.Header "Cluster0", T.Header "Cluster1"]) rest
where leftcoll = map (`indexEx` 0) tab
rest = map (drop 1) tab
When I try to compile it, I get the following errors:
Couldn't match type ‘Int’ with ‘T.Header Int’
Expected type: [T.Header Int]
Actual type: [Int]
In the second argument of ‘map’, namely ‘leftcoll’
In the second argument of ‘T.Group’, namely
‘(map T.Header leftcoll)’
Couldn't match expected type ‘T.Header Text’
with actual type ‘Text’
In the first argument of ‘T.Header’, namely ‘lbl’
In the expression: T.Header lbl
I have absolutely no clue why this is the case. From the Table type documentation and example, it would appear that I simply have to apply the Header constructor to a list of values and then put them inside the Group constructor to get a whole row (or column) of values, but the errors there seem to suggest that the lists (and data) I'm passing as arguments to the Header constructor already need to be Headers. Thus, I'm confused about what the type system is telling me here, and how to get what I want.
Essentially, the table should look something like this:
Foo All Cluster0 Cluster1
=========================
1 10 3 7
2 11 10 1
....
It took me a while to find this one, because there is no problem in the definition of your function: it's the type declaration that is wrong.
Let's take a look at the definition of Table:
data Table rh ch a = Table (Header rh) (Header ch) [[a]]
The column header and row header type paramater are already warped in the Header type, so there no need to do it once more.
Instead of defining:
tabulate :: Text -> [[Int]] -> T.Table (T.Header Int) (T.Header Text) Int
you can defined:
tabulate :: Text -> [[Int]] -> T.Table Int Text Int
To debug that kind of things, I usually extract part of the expression to a where clause, along with a type annotation that tells the compiler what each the expression should be. This often gets me better error messages. For example, here, I extracted:
where tagada :: [T.Header Int]
tagada = map T.Header leftcoll
In the error, I could read:
Expected type: [T.Header (T.Header Int)]
Actual type: [T.Header Int]
That's when I realized that the Header type was maybe used twice.

Convert type family instances to Int

I have this code:
type family Id obj :: *
type instance Id Box = Int
And I want to make it so I can always get an Int from the Id type family. I recognize that a conversion will be required.
I thought maybe creating a class would work:
class IdToInt a where
idToInt :: Id a -> Int
instance IdToInt Box where
idToInt s = s
And that actually compiles. But when I try to use it:
testFunc :: Id a -> Int
testFunc x = idToInt x
I get error:
src/Snowfall/Spatial.hs:29:22:
Couldn't match type `Id a0' with `Id a'
NB: `Id' is a type function, and may not be injective
In the first argument of `idToInt', namely `x'
In the expression: idToInt x
In an equation for `testFunc': testFunc x = idToInt x
So, how can I create a conversion for a type family Id to get an Int?
Based on the answer by ehird, I tried the following but it doesn't work either:
class IdStuff a where
type Id a :: *
idToInt :: Id a -> Int
instance IdStuff Box where
type Id Box = Int
idToInt s = s
testFunc :: (IdStuff a) => Id a -> Int
testFunc x = idToInt x
It gives error:
src/Snowfall/Spatial.hs:45:22:
Could not deduce (Id a0 ~ Id a)
from the context (IdStuff a)
bound by the type signature for
testFunc :: IdStuff a => Id a -> Int
at src/Snowfall/Spatial.hs:45:1-22
NB: `Id' is a type function, and may not be injective
In the first argument of `idToInt', namely `x'
In the expression: idToInt x
In an equation for `testFunc': testFunc x = idToInt x
You can't. You'll need testFunc :: (IdToInt a) => Id a -> Int. Type families are open, so anyone can declare
type instance Id Blah = ()
at any time, and offer no conversion function. The best thing to do is to put the type family in the class:
class HasId a where
type Id a
idToInt :: Id a -> Int
instance IdToInt Box where
type Id Box = Int
idToInt s = s
You'll still need the context, though.
You cannot use a function of type IdToInt a => Id a -> Int because there is no way to determine what type a is. The following example demonstrates this.
type family Id a :: *
type instance Id () = Int
type instance Id Char = Int
class IdToInt a where idToInt :: Id a -> Int
instance IdToInt () where idToInt x = x + 1
instance IdToInt Char where idToInt x = x - 1
main = print $ idToInt 1
Because Id () = Id Char = Int, the type of idToInt in the above context is Int -> Int, which is equal to Id () -> Int and Id Char -> Int. Remember that overloaded methods are chosen based on type. Both class instances define idToInt functions that have type Int -> Int, so the type checker cannot decide which one to use.
You should use a data family instead of a type family, and declare newtype instances.
data family Id a :: *
newtype instance Id () = IdUnit Int
newtype instance Id Char = IdChar Int
With a newtype instance, Id () and Id Char are both ints, but they have different types. The type of an Id informs the type checker which overloaded function to use.
As others have pointed out, the problem is that the compiler can't figure out which a to use. Data families are one solution, but an alternative that's sometimes easier to work with is to use a type witness.
Change your class to
class IdToInt a where
idToInt :: a -> Id a -> Int
instance IdToInt Box where
idToInt _ s = s
-- if you use this a lot, it's sometimes useful to create type witnesses to use
box = undefined :: Box
-- you can use it like
idToInt box someId
-- or
idToInt someBox (getId someBox)
The question you need to answer is, for any given Id, is there only one type a it should appear with? That is, is there a one to one correspondence between as and Id as? If so, data families are the correct approach. If not, you may prefer a witness.

Writing A Function Polymorphic In A Type Family

I was experimenting with type families yesterday and ran into an obstacle with the following code:
{-# LANGUAGE TypeFamilies #-}
class C a where
type A a
myLength :: A a -> Int
instance C String where
type A String = [String]
myLength = length
instance C Int where
type A Int = [Int]
myLength = length
main = let a1 = [1,2,3]
a2 = ["hello","world"]
in print (myLength a1)
>> print (myLength a2)
Here I have a type associated with class C and a function that calculates the length of the associated type. However the above code gives me this error:
/tmp/type-families.hs:18:30:
Couldn't match type `A a1' with `[a]'
In the first argument of `myLength', namely `a1'
In the first argument of `print', namely `(myLength a1)'
In the first argument of `(>>)', namely `print (myLength a1)'
/tmp/type-families.hs:19:30:
Couldn't match type `A a2' with `[[Char]]'
In the first argument of `myLength', namely `a2'
In the first argument of `print', namely `(myLength a2)'
In the second argument of `(>>)', namely `print (myLength a2)'
Failed, modules loaded: none.
If, however I change "type" to "data" the code compiles and works:
{-# LANGUAGE TypeFamilies #-}
class C a where
data A a
myLength :: A a -> Int
instance C String where
data A String = S [String]
myLength (S a) = length a
instance C Int where
data A Int = I [Int]
myLength (I a) = length a
main = let a1 = I [1,2,3]
a2 = S ["hello","world"]
in
print (myLength a1) >>
print (myLength a2)
Why does "length" not work as expected in the first case? The lines "type A String ..." and "type A Int ..." specify that the type "A a" is a list so myLength should have the following types respectively : "myLength :: [String] -> Int" or "myLength :: [Int] -> Int".
Hm. Let's forget about types for a moment.
Let's say you have two functions:
import qualified Data.IntMap as IM
a :: Int -> Float
a x = fromInteger (x * x) / 2
l :: Int -> String
l x = fromMaybe "" $ IM.lookup x im
where im = IM.fromList -- etc...
Say there exists some value n :: Int that you care about. Given only the value of a n, how do you find the value of l n? You don't, of course.
How is this relevant? Well, the type of myLength is A a -> Int, where A a is the result of applying the "type function" A to some type a. However, myLength being part of a type class, the class parameter a is used to select which implementation of myLength to use. So, given a value of some specific type B, applying myLength to it gives a type of B -> Int, where B ~ A a and you need to know the a in order to look up the implementation of myLength. Given only the value of A a, how do you find the value of a? You don't, of course.
You could reasonably object that in your code here, the function A is invertible, unlike the a function in my earlier example. This is true, but the compiler can't do anything with that because of the open world assumption where type classes are involved; your module could, in theory, be imported by another module that defines its own instance, e.g.:
instance C Bool where
type A Bool = [String]
Silly? Yes. Valid code? Also yes.
In many cases, the use of constructors in Haskell serves to create trivially injective functions: The constructor introduces a new entity that is defined only and uniquely by the arguments it's given, making it simple to recover the original values. This is precisely the difference between the two versions of your code; the data family makes the type function invertible by defining a new, distinct type for each argument.

Resources