函数需要newtype的结构,而不是newtype本身

时间:2015-12-04 15:58:39

标签: haskell types

我似乎错过了一些基本的东西。

当我尝试使用sampleGraph映射联接时出现此错误:

Main> map join sampleGraph 

<interactive>:3:10:
    Couldn't match expected type ‘[(Start, [End])]’
            with actual type ‘Graph’
    In the second argument of ‘map’, namely ‘sampleGraph’
    In the expression: map join sampleGraph

这是代码

type Node = Integer
type Edge = (Node,Node)
type Start = Node
type End = Node
newtype Graph = Graph [(Start,[End])] deriving (Eq,Show)

join :: (Start, [End]) -> [Edge]
join (start, ends) = map (\ e -> if start < e then (start, e) else (e, start)) ends

sampleGraph = (Graph
    [(5,[1,2,3]),
     (7,[1,2]),
     (1,[1,2]),
     (2,[1,2])
    ])

1 个答案:

答案 0 :(得分:3)

地图的类型是

map :: (a -> b) -> [a] -> [b]

在这种情况下,join具有类型

join :: (Start, [End]) -> [Edge]

所以map join的类型为

map join :: [(Start, [End])] -> [[Edge]]

我们想要的是Graph -> [[Edge]]。所以我们需要一个函数Graph -> [(Start, [End])],我们将全部设置好。幸运的是,对于记录访问器来说这非常简单!

type Node = Integer
type Edge = (Node, Node)
type Start = Node
type End = Node

newtype Graph = Graph {
  edges :: [(Start, [End])]
} deriving (Eq, Show)

join :: (Start, [End]) -> [Edge]
join (start, ends) = map (\e -> if start < e then (start, e) else (e, start)) ends

sampleGraph =
  Graph [(5, [1, 2, 3]),
         (7, [1, 2]),
         (1, [1, 2]),
         (2, [1, 2])
        ]

foo = map join . edges

我们为edge字段声明了一个访问者edges,并自动赋予Graph -> (Start, [End])类型。撰写map join . edges会产生最终所需的类型。

另一种方法是使用case-expression将Graph破坏为其组成部分:

case sampleGraph of
   Graph edges -> map join edges

生活是一种选择的自助餐。