Я прошел через «Изучай себя на Haskell» и пытаюсь реализовать задачу «Хитроу в Лондон» [1] монадическим способом (вместо сгибов или явных рекурсий). [1] http://learnyouahaskell.com/functionally-solving-problems#heathrow-to-london
Мой вопрос таков: и instance Applicative Route where
, и instance Applicative Route a where
заставляют GHC жаловаться, как показано ниже. Таким образом, включение параметра типа является неправильным, но не включение также является неправильным. Как мне преодолеть это путем минимального изменения кода (его идеи реализации)? См. реализацию ниже ошибки GHC.
Prelude> :r
[1 of 1] Compiling Main ( heathrowToLondon.hs, interpreted )
heathrowToLondon.hs:70:10: error:
• Expecting one fewer argument to ‘Applicative Route’
Expected kind ‘k0 -> Constraint’,
but ‘Applicative Route’ has kind ‘Constraint’
• In the instance declaration for ‘Applicative Route a’
Failed, modules loaded: none.
Prelude> :r
[1 of 1] Compiling Main ( heathrowToLondon.hs, interpreted )
heathrowToLondon.hs:70:10: error:
• The type synonym ‘Route’ should have 1 argument, but has been given none
• In the instance declaration for ‘Applicative Route’
Failed, modules loaded: none.
Моя реализация была такой: подумайте о каждой улице (одна улица выше, одна улица ниже и пересекающий проспект) как Street
, затем подумайте о Route
как обо всем маршруте до сих пор, а также о совокупных затратах на переход Up
или Down
дальше. Тогда mempty
или pure
для Route
будет что-то вроде ([], (0,0))
. Мы определяем бинарную операцию от join
до Route
, затем мы можем получить >=
, используя fmap
и join
. Частичный код ниже:
{-# LANGUAGE TypeSynonymInstances #-}
import Data.List
import Data.List.Extra (chunksOf)
import Control.Monad
-- Try this:
-- solvePath [50, 10, 30, 5, 90, 20, 40, 2, 25, 10, 8]
data Path = Up | Down deriving (Show, Eq, Read)
type Costs a = (a, a)
type Street a = [a]
type Route a = ([Path], Costs a)
-- Monadic!?
toRoute :: (Num a, Ord a) => Street a -> Route a
toRoute [x,y,z] = ([], (min x (y+z), min y (x+z)))
toRoute _ = ([], (0,0))
instance Applicative Route where -- putting or not putting this `a` here doesn't work
pure x = toRoute x -- turns [1,2,5] Street value
f <*> g = undefined
-- Irrelevant to this question but does the job
-- Using explicit recursion
solvePath :: (Num a, Ord a) => Street a -> [Path]
solvePath xs = reverse . crossStreet (0,0) [] $ 0:xs
crossStreet :: (Num a, Ord a) => Costs a -> [Path] -> Street a -> [Path]
crossStreet (a,b) rd street
| null street = rd
| a > b = crossStreet (a',b') (Down:rd) street'
| a == b && a' >= b' = crossStreet (a',b') (Down:rd) street'
| otherwise = crossStreet (a',b') (Up:rd) street'
where (a',b') = (a + min x (y+z), b + min y (x+z))
(x:y:z:street') = street
-- Using folds
solvePath' = reverse . fst . foldl' crossStreet' ([], (0,0)) . chunksOf 3 . (0:)
crossStreet' :: (Num a, Ord a) => Route a -> Street a -> Route a
crossStreet' (ps, (a,b)) [] = (ps, (a,b))
crossStreet' (ps, (a,b)) [x,y,z] = (ps', (a', b'))
where (a',b') = (a + min x (y+z), b + min y (x+z))
ps' = p:ps
p | a > b || ((a==b) && a' >= b') = Down
| otherwise = Up
Изменить №1
Основываясь на комментариях, я изменил определение маршрута на RouteM
, используя data
, и теперь первоначальная жалоба решена. Однако мне все еще нужно выяснить, как реализовать <*>
.
data RouteM a = RouteM {getPath :: [Path], getCost :: Costs a} deriving (Show, Eq, Read)
-- Monadic!?
toRouteM :: (Num a, Ord a) => Street a -> RouteM a
toRouteM [x,y,z] = RouteM [] (min x (y+z), min y (x+z))
toRouteM _ = RouteM [] (0, 0)
instance Functor RouteM where -- putting or not putting this `a` here doesn't work
fmap f r = RouteM (getPath r) (f . fst $ getCost r, f . snd $ getCost r)
instance Applicative RouteM where -- putting or not putting this `a` here doesn't work
pure x = RouteM [] (x, x)
f <*> r = undefined
type Route a = ...
наdata Route a = Route ...
, чтобы создать новый тип для определения экземпляров. Кроме того, хотя в данном случае верным являетсяinstance Applicative Route ...
, стоит отметить, что вы, вероятно, хотели попробоватьinstance Applicative (Route a)
, неinstance Applicative Route a
. Последний является синтаксисом для многопараметрического класса типов. - person Alexis King   schedule 28.04.2017