2017-01-08 2 views
0

다음과 같은 선언을 모나드 컴파일러로 선언하려면 어떻게해야합니까?모나드 클래스를 올바르게 정의하기

module Main where 

instance Monad m where 
    -- "return" constructs a one-item list. 
    return x = [x] 
    -- "bind" concatenates the lists obtained by applying f to each item in list xs. 
    xs >>= f = concat (map f xs) 
    -- The zero object is an empty list. 
    mzero = [] 

현재 나는 다음과 같은 오류가 발생합니다 :

monad_ex1.hs:9:3: ‘mzero’ is not a (visible) method of class ‘Monad’ 

내 코드 https://en.wikipedia.org/wiki/Monad_(functional_programming)#Collections에서, 목표는, 그에서 컴파일 가능한 코드를 생성 실행 ghci에서 그것을 가져 와서 놀러입니다. 코드에서

제거 mzero 다른 비밀 메시지로 연결 :

Illegal instance declaration for ‘Monad m’ 
     (All instance types must be of the form (T a1 ... an) 
     where a1 ... an are *distinct type variables*, 
     and each type variable appears at most once in the instance head. 
     Use FlexibleInstances if you want to disable this.) 
    In the instance declaration for ‘Monad m’ 
+0

오류가 말하듯이 모나드에는 "제로 객체"또는 "mzero"가 없습니다. – melpomene

+2

'인스턴스 모나드 m '은 모든 가능한 유형을'm '이'모나드 '의 인스턴스로 만듭니다. '인스턴스 Monad []'가 필요 하겠지만 이미 표준 라이브러리에 존재합니다. 이와 같은 인스턴스를 제공하려면 자신의 클래스 또는 자신의 유형을 정의해야합니다. – melpomene

+0

모나드 타입 클래스에 대한 인스턴스를 정의하는 동안 왜 'mzero'를 추가했는지 명확하지 않습니다. – BarbedWire

답변

3

코멘트에 포함되는 대부분 여기에 몇 가지 잠재적 인 함정이 있습니다 :

  • 가 정의 된 mzero이 없다가 Monad 인스턴스의 경우, 지정하려고하면 오류가 발생합니다. mzeroMonadPlus 인스턴스에 정의됩니다 (있는 경우).
  • 내장 목록에 대한 모나드 인스턴스를 재정의하려는 시도는 작동하지 않습니다. 이 기능을 사용하려면 자신의 List 유형을 정의해야합니다.
  • FunctorApplicative 인스턴스를 정의해야하기 때문에 "modern"Haskell (GHC 7.10부터)에서 Applicative => Monad Proposal을 구현하면 오래된 Monad 튜토리얼을 폐기하고 사용자 정의 Monads를 작성하기가 약간 어려워졌습니다 detailed migration instructions).

여기 GHC 7.10 호환 상용구를 사용하는 List 사용자 정의 사용자 정의를 사용하는 목록 예의 번역이 나와 있습니다. return의 정의는 Applicative 인스턴스의 pure으로 대신 이동합니다.

module MyListMonad where 

import Control.Monad 

data List a = Empty | Cons a (List a) deriving (Show, Eq) 

instance Functor List where 
    fmap = liftM      -- boilerplate 
instance Applicative List where 
    pure x = Cons x Empty    -- put definition of `return` here 
    (<*>) = ap 
instance Monad List where 
    return = pure      -- boilerplate 
    (>>) = (*>)      -- boilerplate 
    xs >>= f = myConcat (myMap f xs) -- bind definition here 

myConcat :: List (List a) -> List a 
myConcat (Cons lst rest) = myAppend lst (myConcat rest) 
myConcat Empty = Empty 

myAppend :: List a -> List a -> List a 
myAppend (Cons x rest) ys = Cons x (myAppend rest ys) 
myAppend Empty ys = ys 

myMap :: (a -> b) -> List a -> List b 
myMap f (Cons x rest) = Cons (f x) (myMap f rest) 
myMap _ Empty = Empty 

test = do x <- Cons 1 $ Cons 2 $ Cons 3 Empty 
      y <- Cons 4 $ Cons 5 $ Empty 
      return (x * y)