help with use of functional dependencies

你。 提交于 2019-12-11 05:19:47

问题


I have a question about functional dependencies. My understanding was that, for example, if I write class Graph g a b | g -> a, g -> b, then any specific g can be associated with only one type of a and b. Indeed, trying to declare two instance with the same g and different a and b does not work.

However, the compiler (ghc) seems unable to use the dependency in the following case,

class (Eq a, Eq b) => Graph g a b | g -> a, g -> b where
    edges :: g -> [b]
    src :: g -> b -> a
    dst :: g -> b -> a

    vertices :: g -> [a]
    vertices g = List.nub $ map (src g) (edges g) ++ map (dst g) (edges g)

class Graph g a b => Subgraph g a b | g -> a, g -> b where
    extVertices :: g -> [b]

data Subgraph1 g where
    Subgraph1 :: Graph g a b => g -> [b] -> Subgraph1 g

instance Graph g a b => Graph (Subgraph1 g) a b where
    vertices (Subgraph1 g _) = vertices g
    edges (Subgraph1 g _) = edges g
    src (Subgraph1 g _) = src g
    dst (Subgraph1 g _) = dst g

If I revise Subgraph1 by adding the parameters a and b to the type signature, then everything works out.

data Subgraph1 g a b where
    Subgraph1 :: Graph g a b => g -> [b] -> Subgraph1 g a b

回答1:


Don't use fundeps, they are too much pain. Use associated types.

class (Eq (Vertex g), Eq (Edge g)) => Graph g where
  type Edge   g :: *
  type Vertex g :: *

  edges :: g -> [Edge g]
  src   :: g -> Edge g -> Vertex g
  dst   :: g -> Edge g -> Vertex g

  vertices :: g -> [Vertex g]
  vertices g = nub $ map (src g) (edges g) ++ map (dst g) (edges g)

class Graph g => Subgraph g where
  extVertices :: g -> [Edge g]

data Subgraph1 g where
    Subgraph1 :: Graph g => g -> [Edge g] -> Subgraph1 g

instance Graph g => Graph (Subgraph1 g) where
    type Edge (Subgraph1 g) = Edge g
    type Vertex (Subgraph1 g) = Vertex g
    vertices (Subgraph1 g _) = vertices g
    edges (Subgraph1 g _) = edges g
    src (Subgraph1 g _) = src g
    dst (Subgraph1 g _) = dst g

This looks somewhat more readable. Edge g is the type of g's edges, etc.

Note that I translated your code mechanically, without understanding what Subgraph1 does. Why do you need a GADT here, and what the second argument of the data constructor means? It is not used anywhere.



来源:https://stackoverflow.com/questions/6798778/help-with-use-of-functional-dependencies

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!