Convert type family instances to Int - haskell

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.

Related

How do you define a function type in Haskell?

I'm trying to store a function type in a definition so I can reuse it, but Haskell doesn't let me do it. A function type is not a data type , nor a class, as far as I understand them. So what am I doing wrong please?
functionType = Int -> Int -> Int -> Int -> Int -> Int -> Int
myfunction :: functionType -- <-- how do I declare this thing in a definition?
myfunction a b c d e f = a*b*c*d*e*f
Type aliases use the type keyword in their declaration; also, as usual for the declaration of new type forms, the newly declared alias must start with an upper case letter*. So:
type FunctionType = Int -> Int -- -> ...
functionValue :: FunctionType
functionValue a = a
* ...or punctuation. Why doesn't the usual "upper-case" punctuation restriction apply? No idea. I never thought about it before trying to write this answer, and now that I have, I find that a bit weird. Perhaps the upper-case restriction on the declaration of new types should be removed!

Syntax in Functions (Expected kind `* -> Constraint', but `Int' has kind `*') [duplicate]

This question already has answers here:
`String' is applied to too many type arguments
(2 answers)
Closed 2 years ago.
I'm starting to learn Haskell and I'm struggling with syntax in Functions. I'm trying to create a function that receives a Number 'e' and a Number 'n', returning a list with of 'n' times 'e'.
Example: repn 3 5 would return [3,3,3,3,3]:
repn :: Int a => a -> a -> [a]
repn e n
| n >= 1 = (take n (repeat e))
| otherwise = []
But I'm getting this error:
* Expected kind `* -> Constraint', but `Int' has kind `*'
* In the type signature: replica :: Int a => a -> a
As a rule of thumb, writing something of the form Foo a => ... only makes sense of Foo is a type class. Unlike in OO languages, a class and a type in Haskell are completely different things. Int is a type, therefore it cannot be used in this way; instead you should simply use
repn :: Int -> Int -> [Int]
...though actually there's no reason to restrict the list-element type at all, the signature could as well be
repn :: a -> Int -> [a]
Alternatively, you can use a type class: the class of “int-like types” is Integral. Then you can't use take directly, as that is restricted to Int for the counter argument; however you can convert any integral type to Int:
repn :: Integral n => a -> n -> [a]
repn e n = take (fromIntegral n) $ repeat e
-- Note no case distinction is needed, because `take` already yields
-- an empty list if `n<1`.
Your type definition is not correct. The double arrow is used to show required typeclasses (aka kind * -> Constraint), or a constraint on types. However, Int is itself a type (aka kind *).
You can't specify types in this way. In your implementation, n must be an Int, but e could be anything. Since you specify that it should be a number, though, you can constrain it with the Num typeclass. The correct version of your signature therefore is:
repn :: Num a => a -> Int -> [a]
If you want e to be constrained to an Int, then your signature should be
repn :: Int -> Int -> [Int]
If you don't need any constraints on e, your signature can be
repn :: a -> Int -> [a]
These are all valid type signatures for the function you have written. (Though in actual code, I would just point you to the builtin replicate function.)

How to get custom data type member?

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.

How to tell GHC what fromIntegral should do

data N_ary = N_ary Int String Int deriving Eq
stores numbers to various bases. For example 15 to the bases 2, 10, and 16 are N_ary 1 "1111" 2, N_ary 1 "15" 10, and N_ary 1 "F" 16 respectively. (The first field is -1, 0, or 1 as a sign.)
I defined an operator infixl 5 ~> for converting things into N_ary objects and a class for convertible types.
class N_aryAble a where
(~>) :: a -> Int -> N_ary
I had no problems with instance N_aryAble Integer or instance N_aryAble N_ary (to change one base to another), but I ran into a problem with
instance N_aryAble Int where
int ~> base = fromIntegral int ~> base
Ambiguous type variable ‘a0’ arising from a use of ‘fromIntegral’
prevents the constraint ‘(Num a0)’ from being solved.
...
Ambiguous type variable ‘a0’ arising from a use of ‘~>’
prevents the constraint ‘(N_aryAble a0)’ from being solved.
...
Type signatures within instance declarations are not allowed without a special setting.
instance N_aryAble Int where
(~>) :: Int -> Int -> N_ary
int ~> base = fromIntegral int ~> base
Illegal type signature in instance declaration:
(~>) :: Int -> Int -> N_ary
(Use InstanceSigs to allow this)
The following works.
instance N_aryAble Int where
int ~> base = fromIntegral int + (0::Integer) ~> base
> (5::Int) ~> 2 ==> N_ary 1 "101" 2
But that seems ugly and ad hoc. Is there a better way?
Thanks.
You can provide a type annotation to the fromIntegral call, so to make it non ambiguous.
instance N_aryAble Int where
int ~> base = (fromIntegral int :: Integer) ~> base
The problem is not that the compiler can't deduce what from to convert the type from. That could be fixed with a signature for that particular instance method, which BTW you could write like
instance N_aryAble Int where
(~>) = (~~>)
where (~~>) :: Int -> Int -> N_ary
int ~~> base = fromIntegral int ~> base
But that information is already clear from the class method signature, so it won't help you.
No, the problem is that you don't specify what type to convert to, and because the argument to ~> is again polymorphic the compiler has nothing else to infer it from. This could as well convert Int to Int, causing an infinite recursion loop because you end up with the same ~> instantiation you're trying to define!
You can either clarify this with a signature to the result of fromIntegral as shown by chi, or you can simply use the to--version of the conversion function that's monomorphic with an Integer result:
instance N_aryAble Int where
int ~> base = toInteger int ~> base

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