繁体   English   中英

在Haskell中输入类 - 当选择的类型无关紧要时,如何让GHC选择类型?

[英]Type Classes in Haskell - how can I make GHC make a choice of types, when the type chosen doesn't matter?

这是关于在Haskell中使用类型类的问题。

我在尝试编译代码时遇到错误(下面)(下面和https://github.com/chrisdew/haskell-sandbox/blob/master/not_working_but_clean.hs )。

作为刚刚学习Haskell的人,我尝试过遵循GHC的建议,但我认为原因是不同的。

我认为问题是'IO String'或普通'String'类型都可以是'lhello - >> lbracket'的类型,但GHC不知道哪个。

问题是无关紧要,两种类型都可以正常工作。

我已经在https://github.com/chrisdew/haskell-sandbox/blob/master/working_but_ugly.hs上发布了该代码的工作版本。 这将一个 - >>运算符替换为一个新的(非类型类)运算符' - >>>',它强制'lhello - >> lbracket'为'IO String'类型。

  • 我的分析是否正确? 或者还有其他事情发生在这里?

  • 是否有任何方式告知GHC'lhello - >> lbracket'的类型无关紧要,应该选择两种可能性中的任何一种。 或者也许是一个LANGUAGE选项,它允许我指定'最新声明的匹配的类实例获胜',如果有任何未定的。

谢谢,

克里斯。

错误:

chris@chris-linux-desktop:~/nonworkspace/haskell-sandbox$ ghc
not_working_but_clean.hs

not_working_but_clean.hs:40:16:

   No instance for (Stream (IO String) (IO String) (IO String) d)
     arising from a use of '->>' at not_working_but_clean.hs:40:16-34
   Possible fix:
     add an instance declaration for
     (Stream (IO String) (IO String) (IO String) d)
   In the first argument of '(->>)', namely 'lhello ->> lbracket'
   In the second argument of '($)', namely
       'lhello ->> lbracket ->> putStrLn'
   In a stmt of a 'do' expression:
         forkIO $ lhello ->> lbracket ->> putStrLn

not_working_but_clean.hs:40:16:
   No instance for (Stream d String (IO ()) (IO ()))
     arising from a use of `->>' at not_working_but_clean.hs:40:16-47
   Possible fix:
     add an instance declaration for (Stream d String (IO ()) (IO ()))
   In the second argument of `($)', namely
       `lhello ->> lbracket ->> putStrLn'
   In a stmt of a 'do' expression:
         forkIO $ lhello ->> lbracket ->> putStrLn
   In the expression:
       do { forkIO $ (bracket $ hello) ->> putStrLn;
            forkIO $ lhello ->> lbracket ->> putStrLn;
        forkIO $ bracket hello ->> putStrLn;
            forkIO $ lbracket lhello ->> putStrLn;
          .... }

not_working_but_clean.hs:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
TypeSynonymInstances, OverlappingInstances #-}
{-# OPTIONS_GHC #-}

module Main (
main
)
where

import Control.Concurrent (forkIO, MVar, newEmptyMVar, putMVar,
takeMVar, ThreadId, threadDelay)
import Control.Monad (forever, liftM)

class Stream a b c d where
   (->>) :: a -> (b -> c) -> d

instance Stream (IO d) d (IO c) (IO c) where
   f ->> g = f >>= g

instance Stream d d (IO c) (IO c) where
   f ->> g = g f

instance Stream d d c c where
   x ->> y = y $ x

-- This simply wraps a string in brackets.
bracket :: String -> String
bracket x = "(" ++ x ++ ")"

lbracket :: IO String -> IO String
lbracket x = liftM bracket x

hello :: String
hello = "Hello World!"

lhello :: IO String
lhello = do return hello

main :: IO ()
main = do
      forkIO $ (bracket $ hello) ->> putStrLn
      forkIO $ lhello ->> lbracket ->> putStrLn
      forkIO $ bracket hello ->> putStrLn
      forkIO $ lbracket lhello ->> putStrLn
      threadDelay 10000000 -- Sleep for at least 10 seconds before exiting.

working_but_ugly.hs:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
TypeSynonymInstances, OverlappingInstances #-}
{-# OPTIONS_GHC #-}

module Main (
main
)
where

import Control.Concurrent (forkIO, MVar, newEmptyMVar, putMVar,
takeMVar, ThreadId, threadDelay)
import Control.Monad (forever, liftM)

class Stream a b c d where
   (->>) :: a -> (b -> c) -> d

instance Stream (IO d) d (IO c) (IO c) where
   f ->> g = f >>= g

instance Stream d d (IO c) (IO c) where
   f ->> g = g f

instance Stream d d c c where
   x ->> y = y $ x

x ->>> y = y $ x

-- This simply wraps a string in brackets.
bracket :: String -> String
bracket x = "(" ++ x ++ ")"

lbracket :: IO String -> IO String
lbracket x = liftM bracket x

hello :: String
hello = "Hello World!"

lhello :: IO String
lhello = do return hello

main :: IO ()
main = do
      forkIO $ (bracket $ hello) ->> putStrLn
      forkIO $ lhello ->>> lbracket ->> putStrLn
      forkIO $ bracket hello ->> putStrLn
      forkIO $ lbracket lhello ->> putStrLn
      threadDelay 10000000 -- Sleep for at least 10 seconds before exiting.

不,没有办法让GHC翻转硬币并选择一个。

你的所有实例的类型'c'都与类型'd'相同,所以你可以省略类型'd'并在定义Stream时重用类型'c'。

instance Stream d d (IO c) (IO c) where
   f ->> g = g f

instance Stream d d c c where
   x ->> y = y $ x

以上都是一样的。 “gf”和“y $ x”是相同的。 那为什么两个不同的实例?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM