我正在经历"了解自己一个Haskell"我正试图将希思罗机场推向伦敦"问题[1]采用Monadic方式(而不是折叠或显式递归)。 [1] http://learnyouahaskell.com/functionally-solving-problems#heathrow-to-london
我的问题是:instance Applicative Route a where
和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.
使GHC抱怨如下。所以包含一个类型参数是错误的,但不包含也是错误的。如何通过对代码的最小更改(其实现思路)来克服这个问题?请参阅GHC错误下面的实现。
Street
我的实施是这样的:想想每条街道(上面一条街道,一条街道和一条横穿大道)的费用为Route
,然后将Up
视为所有路线,直到现在为止作为下一步Down
或mempty
的累计费用。然后,pure
的{{1}}或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
根据评论,我使用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
答案 0 :(得分:0)
我不确定你的路线类型/是/应用,或为什么它应该是。
Route path (f,g) <*> Route path' (x,y)
意味着什么?
您在这里缺少相关信息。 (即上/下街的费用。)
您的Route / RouteM类型不构成应用程序的方式。
我还要定义type Block a = {getUp::a,getDown:a,getCross:a)
和type Street a = [Block]
。然后定义Route a -> Block a -> Route a
。