를 생성 잘못된 코드 (also on lpaste.net)이다 :여기에 이상한 행동을
module Data.Graph.Dijkstra
(dijkstra
, dijkstraPath
) where
-- Graph library import
import Data.Graph.Inductive hiding (dijkstra)
-- Priority queue import
import qualified Data.PQueue.Prio.Min as PQ
-- Standard imports
import Data.List (find)
import Data.Maybe (fromJust)
import Data.Monoid
-- Internal routine implementing Dijkstra's shortest paths
-- algorithm. Deemed internal because it needs to be kickstarted with
-- a singleton node queue. Based on FGL's current implementation of
-- Dijkstra.
dijkstraInternal ::
(Graph gr, Ord b, Monoid b) => gr a b -> PQ.MinPQueue b [Node] -> [[Node]]
dijkstraInternal g q
| PQ.null q = []
| otherwise =
case match v g of
(Just cxt,g') -> p:dijkstraInternal g' (PQ.unions (q' : expand cxt minDist p))
(Nothing, g') -> dijkstraInternal g' q'
where ((minDist,[email protected](v:_)), q') = PQ.deleteFindMin q
expand (_,_,_,s) dist pathToC =
map (\(edgeCost,n) -> PQ.singleton (dist `mappend` edgeCost) (n:pathToC)) s
-- Given a graph and a start node, returns a list of lists of nodes
-- corresponding to the shortest paths from the start to all other
-- nodes, where the edge costs are accumulated according to the Monoid
-- instance of the edge label type and costs are compared by the edge
-- label's Ord instance.
dijkstra :: (Graph gr, Ord b, Monoid b) => gr a b -> Node -> [[Node]]
dijkstra g start = dijkstraInternal g (PQ.singleton `mempty` [start]) -- !!!
dijkstraPath :: (Graph gr, Ord b, Monoid b) => gr a b -> Node -> Node -> [LNode a]
dijkstraPath g start goal =
let paths = dijkstra g start
pathNodes = find ((goal ==) . head) paths -- Can paths be empty?
in
case pathNodes of
Nothing -> []
Just ps -> reverse $ map (\n -> (n, fromJust $ lab g n)) ps
이상한 것들 라인 (39)에 상기 -- !!!
코멘트 표시. 이 코드는 컴파일되지만 런타임 오류는 무엇이든 상관없이 PQ.singleton
함수가 빈 우선 순위 대기열을 반환합니다. mempty
에 실수로 백틱을 추가 했으므로 코드를 제거하고 예상대로 컴파일했습니다.
그러나 이것은 이상하게 보았습니다. 어떻게 코드가 올바르게 이진 함수가 아닌 mempty
주위의 백틱으로 컴파일 되었습니까? (mempty :: a
)?
는 #haskell에 매우 관대 한 도움이 후, 나는 그것이 기능을위한 모노 이드 인스턴스 함께 할 수있는 뭔가 남겼 :
instance Monoid b => Monoid (a -> b)
내가 지금이 오류가 성공적으로 타입 체크하는 이유에 매우 막연한 이해를하지만, 나는 아직도 어떻게 든 도덕적으로 잘못 생각합니다. 누군가 어떻게 이런 일이 일어 났는지 정확하게 설명 할 수 있습니까?
또한 우선 순위 큐의 singleton
함수에주의를 기울이고 싶습니다. the source에 따르면 빈 큐를 반환하지 않습니다. 그러나 24 행에서 동일한 우선 순위 큐는 즉시 비어있는 것으로 평가됩니다. (I 추적 호출을이을 확인했습니다.)
monoid 인스턴스? # 하스켈이 설명 했으니 까 아직 명확하지 않은가? – bennofs
그들의 설명에서 나는이 특정한 Monoid 인스턴스가 근본 원인이되어야한다는 것을 이해하지만, 나는 그것이 작동하는 방식으로 정확하게 내 머리를 감쌀 수 없다. 또한,이 질문에 대한 대중의 대답은 하스켈 커뮤니티 (나 자신)가 Monoid 인스턴스 (->)를 이해하는 데 정말로 도움이 될 것이라고 믿습니다. – giogadi
이 인스턴스를 두 번 적용 할 수는 없으므로 'c'가 'Monoid'인 경우 'a -> b -> c'가 'Monoid'의 인스턴스이므로 완전한 바이너리 함수입니다. –