How to disambiguate selector function? - haskell

In GHC 8:
{-# LANGUAGE DuplicateRecordFields #-}
data Dog = Dog { name::String }
data Human = Human { name::String }
dog = Dog "Spike"
main = putStrLn $ name dog
This code does not compile:
Ambiguous occurrence `name'
It could refer to either the field `name', defined at A.hs:4:22
or the field `name', defined at A.hs:3:18
How to correctly retrieve the name of my dog?

this should work:
main = putStrLn $ name (dog :: Dog)
see DuplicateRecordFields for details:
Bare uses of the field refer only to the selector function, and work only if this is unambiguous.
and
However, we do not infer the type of the argument to determine the datatype, or have any way of deferring the choice to the constraint solver.
The example there is very much like yours:
bad (p :: Person) = personId p
this will not work when there is another record with a personId field in scope - even if it seems to be obvious :(

Related

Type class polymorphism with overloaded numeric and string literals

I'm trying to write some EDSL for assigning values to keys. So I have the following data type for value:
data Value = B Bool | I Int
I want to have unified way to convert different values to objects of type Value. So I've created the following type class:
class ToValue a where toValue :: a -> Value
instance ToValue Bool where toValue = B
instance ToValue Int where toValue = I
Unfortunately, this code doesn't compile:
foo :: [Value]
foo = [toValue True, toValue 3]
I understand the reason why. But this makes me sad. I don't really understand how to solve this problem... And things become more difficult if I have -XOverloadedStrings enabled and I want to add T Text constructor to my Value type.
My final goal is to have ability to write something like this:
foo :: [(Text, Value)]
foo = [ "key1" !!! True
, "key2" !!! 42
, "key3" !!! "foo"
, "key4" !!! [5, 7, 10]
]
I understand that I can always wrap manually every value into corresponding constuctor but I'd prefer to avoid that (since in my real life constructors are longer than one letter and code doesn't really decrease in noise with constructors).
What can I do to achieve the closest possible implementation? I would like to avoid unsafe Num instance for Value if possible...
Use ExtendedDefaultRules. (It is enabled by default in GHCi, and the pragma enables it in GHC.)
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE OverloadedStrings #-}
default (Int, String)
class Value a where
toValue :: a -> String
instance Value Int where
toValue = show
instance Value String where
toValue = id
main = do
print (toValue 3) -- would otherwise be ambiguous
print (toValue "x")
Old answer
If I understand correctly, the goal here is to keep the syntax uniform while properly specializing literals. One way is to use Template Haskell, so foo might look like
foo = [$(toValue [|True|]), $(toValue [|3|])]
or
foo = [ [toValue| True |], [toValue| 3 |] ]
The latter is less dollar-noisy, but implementing a custom quote requires an expression parser and template-haskell doesn't provide one.

Silly duplicated record fields error

Consider the following:
{-# LANGUAGE DuplicateRecordFields #-}
data A = A { name :: String }
data B = B { name :: String }
main = print $ name (A "Alice")
When compiled, I get the following message (on GHC 8.0.2)
duplicatedrecords.hs:7:16: error:
Ambiguous occurrence ‘name’
It could refer to either the field ‘name’,
defined at duplicatedrecords.hs:5:14
or the field ‘name’, defined at duplicatedrecords.hs:3:14
But if I modify the main line as follows:
main = print $ name ((A "Alice") :: A)
Compilation proceeds successfully.
Why is this? The type signature :: A seems redundant to me, as surely the A constructor makes it clear to the compiler that (A "Alice") is of type A. But for some reason it makes a difference. Why is this and is there a way I can get this to compile without littering extra type signatures everywhere?
Note:
It's worth noting that the following compiles fine:
data A = A { a_name :: String }
data B = B { b_name :: String }
class Name t where
name :: t -> String
instance Name A where name = a_name
instance Name B where name = b_name
main = print $ name (A "Alice")
We can even go further as follows, allowing different result types:
{-# LANGUAGE TypeFamilies #-}
data A = A { a_name :: String }
data B = B { b_name :: Int }
class Name t where
type family T t
name :: t -> T t
instance Name A where
type T A = String
name = a_name
instance Name B where
type T B = Int
name = b_name
main = print $ name (A "Alice")
It seems like GHC just has to mechanically add a class for each unique record name and an instance for each record in each data type. This will mean however that name x == name y not implying that the types of x and y are the same but I'd expect that when using this extension anyway.
Just wondering if there's anything tricky I'm missing here regarding the implementation or that it just needs someone to do it?
-XDuplicateRecordFields currently doesn't infer types from arguments.
See GHC user guide section about this extension.
However, we do not infer the type of the argument to determine the datatype, or have any way of deferring the choice to the constraint solver. Thus the following is ambiguous:
But things are improving. So we might expect and finally get desired behavior:
https://prime.haskell.org/wiki/TypeDirectedNameResolution

how to handle capital case in JSON?

This is a stupid question, and I have tried to understand from different tutorials. When having a JSON with capital case Haskell crashes as explained by others (https://mail.haskell.org/pipermail/beginners/2013-October/012865.html). As suggested it could be solved with deriving from deriveFromJSON. DeriveJSON requires a function input, how should I write the derive statement in the below code? I am missing something in my understanding, and would appreciate any help.
import Data.Aeson.TH
data Person = Person {
Foo :: String
, bar :: String
} deriving (Eq, Show, deriveJSON)
main = do
let b = Person "t" "x"
print b
deriveJSON and friends are Template Haskell functions which will generate instances for you. As such, you should not try to list them in the deriving clause. Instead, call them in a splice at the top level like this:
{-# LANGUAGE TemplateHaskell #-}
import Data.Aeson.TH
data Person = Person {
foo :: String,
bar :: String
} deriving (Eq, Show)
$(deriveJSON defaultOptions ''Person)
As mentioned in the mailing list, you can customize the field names by overriding the fieldLabelModifier function of the defaultOptions record, for example this will change the JSON name of foo to Foo:
$(deriveFromJSON defaultOptions {
fieldLabelModifier = let f "foo" = "Foo"
f other = other
in f
} ''Person)
Do you have any control of the instance being generated? If so, don't emit keys starting with capital letters.
If not: Just define the instance yourself instead of deriving it. It's just a couple lines of code.

Haskell: refer to type of value at compile time

I'm wondering if there's a nice way to refer to types of values without explicitly aliasing them using type in code (not at runtime - there is no reification going on here).
Take the following code (using Data.Vinyl):
{-# LANGUAGE DataKinds, TypeOperators #-}
import Data.Vinyl
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
type Person = ["name" ::: String, "age" ::: Int]
Here we have the types "name" ::: String and "age" ::: Int repeated in two places. If we reuse fields in multiple records, this can become multiple places. Despite the fact that the Person type is really referring to the constituent fields, the type declarations are independent. So changing age to be represented by Float, say, requires changes in various places.
Obviously it's not necessary to explicitly type things, since they will be inferred. However, in my case the record types are being returned from an options parser, and thus exported. Likewise, one could write the following:
type Name = "name" ::: String
name = Field :: Name
type Age = "age" ::: Int
age = Field :: Age
type Person = [Name, Age]
However, this then involves another load of type aliases and double the number of lines. What I would like to be able to write is the following:
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
type Person = [typeof name, typeof age]
This explicitly links the type of a Person to the types of its fields.
Is there a way (preferably sans-TH, but I'd be interested even involving TH) to do this?
It should be easy enough to make a String -> [Name] -> DecsQ function out of
the following. Too bad with ghc7.6 (at least), the check for cycles in type
synonyms seems to stop the prettier type Person = $(listOfT ['name, 'age]) from
working out.
{-# LANGUAGE DataKinds, TemplateHaskell, TypeOperators #-}
import Language.Haskell.TH
import Control.Applicative
import Data.Vinyl
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
let listOfT (n:ns) = do
VarI _ ty _ _ <- reify n
(appT promotedConsT) (return ty) `appT` listOfT ns
listOfT [] = promotedNilT
in return <$> tySynD (mkName "Person") [] (listOfT ['name, 'age])

Accessing members of a custom data type in Haskell

Say I have the following custom data type and function in Haskell:
data Person = Person { first_name :: String,
last_name :: String,
age :: Int
} deriving (Eq, Ord, Show)
If I want to create a function print_age to print a Person's age, like so: print_age (Person "John" "Smith" 21) , how would I write print_age to access the age parameter? I'm an Object Oriented guy, so I'm out of my element here. I'm basically looking for the equivalent of Person.age.
Function application is prefix, so age person would correspond to the person.age() common in OOP languages. The print_age function could be defined pointfree by function composition
print_age = print . age
or point-full
print_age person = print (age person)
This is called record syntax, LYAH has a good section on it.
When a datatype is defined with records, Haskell automatically defines functions with the same name as the record to act as accessors, so in this case age is the accessor for the age field (it has type Person -> Int), and similarly for first_name and last_name.
These are normal Haskell functions and so are called like age person or first_name person.
In addition to the age function mentioned in other answers, it is sometimes convenient to use pattern matching.
print_age Person { age = a } = {- the a variable contains the person's age -}
There is a pretty innocuous extension that allows you to skip the naming bit:
{-# LANGUAGE NamedFieldPuns #-}
print_age Person { age } = {- the age variable contains the person's age -}
...and another, viewed with varying degrees of distrust by various community members, which allows you to even skip saying which fields you want to bring into scope:
{-# LANGUAGE RecordWildCards #-}
print_age Person { .. } = {- first_name, last_name, and age are all defined -}

Resources