应用实例需要1和0个参数

时间:2017-04-27 21:36:28

标签: haskell stack monads state-monad

我正在经历"了解自己一个Haskell"我正试图将希思罗机场推向伦敦"问题[1]采用Monadic方式(而不是折叠或显式递归)。 [1] http://learnyouahaskell.com/functionally-solving-problems#heathrow-to-london

我的问题是:instance Applicative Route a wherePrelude> :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视为所有路线,直到现在为止作为下一步Downmempty的累计费用。然后,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

编辑#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

1 个答案:

答案 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