{"action":"created","issue":{"url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/issues/2","repository_url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous","labels_url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/issues/2/labels{/name}","comments_url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/issues/2/comments","events_url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/issues/2/events","html_url":"https://github.com/natefaubion/purescript-heterogeneous/pull/2","id":371694884,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI0MDg1NDQx","number":2,"title":"Update functional dependencies so multiple operations can be supported on the same underlying record","user":{"login":"thomashoneyman","id":10245104,"node_id":"MDQ6VXNlcjEwMjQ1MTA0","avatar_url":"https://avatars2.githubusercontent.com/u/10245104?v=4","gravatar_id":"","url":"https://api.github.com/users/thomashoneyman","html_url":"https://github.com/thomashoneyman","followers_url":"https://api.github.com/users/thomashoneyman/followers","following_url":"https://api.github.com/users/thomashoneyman/following{/other_user}","gists_url":"https://api.github.com/users/thomashoneyman/gists{/gist_id}","starred_url":"https://api.github.com/users/thomashoneyman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thomashoneyman/subscriptions","organizations_url":"https://api.github.com/users/thomashoneyman/orgs","repos_url":"https://api.github.com/users/thomashoneyman/repos","events_url":"https://api.github.com/users/thomashoneyman/events{/privacy}","received_events_url":"https://api.github.com/users/thomashoneyman/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2018-10-18T20:17:09Z","updated_at":"2018-10-21T22:10:21Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/pulls/2","html_url":"https://github.com/natefaubion/purescript-heterogeneous/pull/2","diff_url":"https://github.com/natefaubion/purescript-heterogeneous/pull/2.diff","patch_url":"https://github.com/natefaubion/purescript-heterogeneous/pull/2.patch"},"body":"Currently, `purescript-heterogeneous` allows you to create functions like these:\r\n\r\n```purescript\r\n-- Count the number of `Either` values in a record that are `Left`\r\ndata CountLeft = CountLeft\r\n\r\ninstance countLeft :: Folding CountLeft Int (Either a b) Int where\r\n  folding CountLeft acc (Left _) = acc + 1\r\n  folding CountLeft acc _ = acc\r\n\r\ncountLefts :: forall r. HFoldl CountLeft Int { | r } Int => { | r } -> Int\r\ncountLefts = hfoldl CountLeft 0\r\n\r\n-- Count the number of `Either` values in a record that are `Right`\r\ndata CountRight = CountRight\r\n\r\ninstance countRight :: Folding CountRight Int (Either a b) Int where\r\n  folding CountRight acc (Right _) = acc + 1\r\n  folding CountRight acc _ = acc\r\n\r\ncountRights :: forall r. HFoldl CountRight Int { | r } Int => { | r } -> Int\r\ncountRights = hfoldl CountRight 0\r\n```\r\n\r\nBut what if you want a function that uses multiple operations?\r\n\r\n```purescript\r\ncountBoth :: forall r.\r\n  HFoldl CountLeft Int { | r } Int =>\r\n  HFoldl CountRight Int { | r } Int =>\r\n  { | r } ->\r\n  Int\r\ncountBoth r = countRights r + countLefts r\r\n```\r\n\r\nThis ought to be valid, but instead causes a compiler error. A record can only match one instance!\r\n\r\n## Solution\r\n\r\nThis PR updates the functional dependencies for the `HFoldl` and `HMap` classes (with help from @monoidmusician) and provides test cases proving that the new functional dependencies support this use case."},"comment":{"url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/issues/comments/431708675","html_url":"https://github.com/natefaubion/purescript-heterogeneous/pull/2#issuecomment-431708675","issue_url":"https://api.github.com/repos/natefaubion/purescript-heterogeneous/issues/2","id":431708675,"node_id":"MDEyOklzc3VlQ29tbWVudDQzMTcwODY3NQ==","user":{"login":"natefaubion","id":144058,"node_id":"MDQ6VXNlcjE0NDA1OA==","avatar_url":"https://avatars1.githubusercontent.com/u/144058?v=4","gravatar_id":"","url":"https://api.github.com/users/natefaubion","html_url":"https://github.com/natefaubion","followers_url":"https://api.github.com/users/natefaubion/followers","following_url":"https://api.github.com/users/natefaubion/following{/other_user}","gists_url":"https://api.github.com/users/natefaubion/gists{/gist_id}","starred_url":"https://api.github.com/users/natefaubion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/natefaubion/subscriptions","organizations_url":"https://api.github.com/users/natefaubion/orgs","repos_url":"https://api.github.com/users/natefaubion/repos","events_url":"https://api.github.com/users/natefaubion/events{/privacy}","received_events_url":"https://api.github.com/users/natefaubion/received_events","type":"User","site_admin":false},"created_at":"2018-10-21T22:10:21Z","updated_at":"2018-10-21T22:10:21Z","author_association":"OWNER","body":"You _can_ use the same variable. This type checks.\r\n```purescript\r\ntestReplaceBoth :: forall rvals r.\r\n  HMapWithIndex (ReplaceLeft rvals) { | r } { | r } =>\r\n  HMapWithIndex (ReplaceRight rvals) { | r } { | r } =>\r\n  { | rvals } ->\r\n  { | r  } ->\r\n  { | r }\r\ntestReplaceBoth vals =\r\n  replaceLeft vals >>> replaceRight vals\r\n```\r\n\r\nBut you didn't do that 😄, if you use distinct type variables, then they are distinct to the compiler. The only way to have them unify again is through some sort of equality constraint."}}
{"actor":{"display_login":"natefaubion"}}